local BattleController = class("BattleController",function() return  display.newLayer() end)

local UIMainView = require("app.battleV3.ui.MainView")
local LocationConfig = import(".BattleLocation")
local EntityFactory = import(".EntityFactory")
local EffectFactory = import(".EffectFactory")
local BattleModel = import(".models.BattleModel")
local EntityFrontLayer = import(".views.EntityFrontLayer")
local newFloatTipsView = require("app.newFloatTips.newFloatTipsView")
local VisualEffect = import(".VisualEffect")
local DBMMgr = require("app.battleV3.ui.DBMMgr")
local ShakeConfig = require("app.configs.ShakeConfig")
local Armature = require("app.public.avatar.Armature")
local Actor = import(".Actor")
local PlayerNode = import(".views.PlayerNode")

local NewerbattleguideController

local Entity =
{
    getId = battle.Entity.getId,
    kind = battle.Entity.kind,
    pos = battle.Entity.pos,
    deceased = battle.Entity.deceased,
    shouldRemove = battle.Entity.shouldRemove,
    face = battle.Entity.face,
    hurtTime = battle.Entity.hurtTime,
    getInitFace = battle.Entity.getInitFace,
    teamId = battle.Entity.teamId,
    fallTime = battle.Entity.fallTime,
}

local Unit = {
    getSkills = battle.Unit.getSkills,
    isStartState = battle.Unit.isStartState,
    isMoveState = battle.Unit.isMoveState,
    isIdleState = battle.Unit.isIdleState,
    isSkillState = battle.Unit.isSkillState,
    calMovePos = battle.Unit.calMovePos,
    isRestrictedState = battle.Unit.isRestrictedState,
    trackSkillInProgress = battle.Unit.trackSkillInProgress,
    skillInHitMoveProgress = battle.Unit.skillInHitMoveProgress,
    skillInChanneling = battle.Unit.skillInChanneling,
    calTrackPos = battle.Unit.calTrackPos,
    npcId = battle.Unit.npcId,
    hp = battle.Unit.hp,
    hpMax = battle.Unit.hpMax,
    speed = battle.Unit.speed,
    baseSpeed = battle.Unit.baseSpeed,
    rage = battle.Unit.rage,
    rageMax = battle.Unit.rageMax,
    energy = battle.Unit.energy,
    energyMax = battle.Unit.energyMax,
    comboPoint = battle.Unit.comboPoint,
    comboPointMax = battle.Unit.comboPointMax,
    mana = battle.Unit.mana,
    manaMax = battle.Unit.manaMax,
    dead = battle.Unit.dead,
    isInCompleteStealth = battle.Unit.isInCompleteStealth,
    isInStealth = battle.Unit.isInStealth,
    isInDisguise = battle.Unit.isInDisguise,
    shouldHideAllHpUI = battle.Unit.shouldHideAllHpUI,
    restricted = battle.Unit.restricted,
    getRestrictedBuffEffect = battle.Unit.getRestrictedBuffEffect,
    getAllRestrictedSkillBuffEffects = battle.Unit.getAllRestrictedSkillBuffEffects,
    superSkillPreProgress = battle.Unit.superSkillPreProgress,
    skillInProgress = battle.Unit.skillInProgress,
    skillInProgressCanBreak = battle.Unit.skillInProgressCanBreak,
    skillRoll = battle.Unit.skillRoll,
    isIdleState = battle.Unit.isIdleState,
    isStartState = battle.Unit.isStartState,
    isHurtState = battle.Unit.isHurtState,
    getFlag = battle.Unit.getFlag,
    getUnitStat = battle.Unit.getUnitStat,
    getNextBasicTargetId = battle.Unit.getNextBasicTargetId,
    isLockSkillTarget = battle.Unit.isLockSkillTarget,
    getManualMoveFlag = battle.Unit.getManualMoveFlag,
    hasBuffTag = battle.Unit.hasBuffTag,
    hasBuffEffect = battle.Unit.hasBuffEffect,
    getTrackTotalDistance = battle.Unit.getTrackTotalDistance,
    getTrackCurrentDistance = battle.Unit.getTrackCurrentDistance,
    getLeftReviveTimes = battle.Unit.getLeftReviveTimes,
    isCanShowPvpReviveUI = battle.Unit.isCanShowPvpReviveUI,
    isManualMoving = battle.Unit.isManualMoving,
    isSummon = battle.Unit.isSummon,
    isSummonerClone = battle.Unit.isSummonerClone,
    unitModelId = battle.Unit.unitModelId,
	getSummonerId = battle.Unit.getSummonerId,
    hpPercent10K = battle.Unit.hpPercent10K,
    getSoul = battle.Unit.getSoul,
    isRefresh = battle.Unit.isRefresh,
    getRelatedNpcUnitId = battle.Unit.getRelatedNpcUnitId,
    getLastUnitModelId = battle.Unit.getLastUnitModelId,
}

local UnitStat = {getTotalDamage = battle.UnitStat.getTotalDamage,
                  getTotalHeal = battle.UnitStat.getTotalHeal,
                  getDeadTimes = battle.UnitStat.getDeadTimes,
                  getAssists   = battle.UnitStat.getAssists,
                  getKillPlayerTimes = battle.UnitStat.getKillPlayerTimes,}

local Projectile_calMovePos = battle.Projectile.calMovePos
local Projectile_speed = battle.Projectile.speed
local Projectile_cfg = battle.Projectile.cfg
local Projectile_getCasterId = battle.Projectile.getCasterId
local Projectile_getTargetId = battle.Projectile.getTargetId

local Skill_name = battle.Skill.name
local Skill_appliedPreReleaseFinish = battle.Skill.appliedPreReleaseFinish
local Skill_isBasicAttack = battle.Skill.isBasicAttack
local Skill_getCanBeBroken = battle.Skill.getCanBeBroken
local Skill_chantD = battle.Skill.chantD
local Skill_isChantSkill = battle.Skill.isChantSkill
local Skill_channelD = battle.Skill.channelD
local Skill_releaseD = battle.Skill.releaseD
local Skill_applyTime = battle.Skill.applyTime
local Skill_loopApplyTime = battle.Skill.loopApplyTime
local Skill_duringReleaseRecover = battle.Skill.duringReleaseRecover
local Skill_inProgressCanBreak = battle.Skill.inProgressCanBreak
local Skill_duringChanting = battle.Skill.duringChanting
local Skill_duringTracking = battle.Skill.duringTracking
local Skill_duringChanneling = battle.Skill.duringChanneling
local Skill_currentSubSkill = battle.Skill.currentSubSkill
local Skill_getIsMarkTarget = battle.Skill.getIsMarkTarget
local Skill_getPredictTargets = battle.Skill.getPredictTargets
local Skill_getPredictTargetsId = battle.Skill.getPredictTargetsId
local Skill_getSkillDamageRangeKind = battle.Skill.getSkillDamageRangeKind
local Skill_targetId = battle.Skill.targetId
local Skill_getLeftChantTime = battle.Skill.getLeftChantTime
local Skill_cfg = battle.Skill.cfg
local Skill_getDamageRange = battle.Skill.getDamageRange
local Skill_getTargetKind = battle.Skill.getTargetKind
local Skill_getReleaseTargetPoint = battle.Skill.getReleaseTargetPoint
local Skill_getKeepShake = battle.Skill.getKeepShake
local Skill_uid = battle.Skill.uid
local Skill_unit = battle.Skill.unit
local Skill_cd = battle.Skill.cd
local Skill_cdD = battle.Skill.cdD
local Skill_getChannelCanMove = battle.Skill.getChannelCanMove

local skillInterface =
{
    getIsShowScreenMask = battle.Skill.getIsShowScreenMask,
    isChanneled = battle.Skill.isChanneled,
    isComboSkill = battle.Skill.isComboSkill,
    hasProjectile = battle.Skill.hasProjectile,
    getProjectileDamageRangeKind = battle.Skill.getProjectileDamageRangeKind,
    getProjectileDamageRange = battle.Skill.getProjectileDamageRange,
    calHitMovePos = battle.Skill.calHitMovePos,
    getTrackType = battle.Skill.getTrackType,
    id = battle.Skill.id,
    canBeBrokenByAccDamage = battle.Skill.canBeBrokenByAccDamage,
    getBeBrokenAccDamage = battle.Skill.getBeBrokenAccDamage,
    getBeBrokenAccDamageMax = battle.Skill.getBeBrokenAccDamageMax,
    getPredictTargetsProjectile = battle.Skill.getPredictTargetsProjectile
}

local EffectConfig_getId = battle.EffectConfig.getId
local SkillConfig_getEffects = battle.SkillConfig.getEffects
local SkillConfig_getProjectiles = battle.SkillConfig.getProjectiles
local SkillConfig_getChannel = battle.SkillConfig.getChannel
local SkillConfig_isSpecialBrokenType = battle.SkillConfig.isSpecialBrokenType

local ProjectileConfig_getEffects = battle.ProjectileConfig.getEffects
local ProjectileConfig_getObjectId = battle.ProjectileConfig.getObjectId

local DebugMode = false
local function debugLog(...)
    if DebugMode then
        print("[battle]",...)
    end
end

local AUTO_SELECT_TARGET = true
function BattleController.createWithUrl(host,port,createParams,extendParams)
	local instance = BattleController.new(extendParams)
    local model = BattleModel.createWithUrl(host,port,createParams)
    instance.model = model
    instance:bindModelEvent(model)
    instance:addChild(model)
	return instance
end

function BattleController:BeginSingleGame()
    self.model:dispatchEvent(self.model.SINGLE_GAME_BEGIN)
end

function BattleController:isFastForward()
    return self.model:isFastForward()
end

function BattleController:isRewind()
    return self.model:isRewind()
end

function BattleController:ctor(params)
	cc(self):addComponent("components.behavior.SimpleEvent"):exportMethods()

    tapm.markLevelLoad("Battle", 0)

    -- 新手战斗引导是否结束标记、默认没有
    NewerbattleguideController = app:getInst( "NewerbattleguideController" )
    self._newerBattleGuideEndedFlag = NewerbattleguideController:isNewerBattleGuideEnded() or false
    app:addCustomEventListener( Constant.BattleNewerGuideEndFlag, function()
        print( " ---------------->>>>>>>> battleController _newerBattleGuideEndedFlag true" )
        self._newerBattleGuideEndedFlag = true
    end, self )

    self.flagReady = false
    self.actorFloatTextVisible = true

    self._state = Enums.BattleState.init

    self.prepareLoadResCountPerFrame = BATTLE_PREPARE_LOAD_COUNT_PER_FRAME

    self.forceUIVisible = {}
    self.forceEnableInput = nil
    self.ignoreTeammateDamage = true
	self.url = nil
	self.model = nil
	self.views = {}
    self.projectileViews = {}
    self.eventCache = {}
    self.altitude = 100
    self.mapRoot = params.mapRoot
    self.maskRootLayer = params.maskRootLayer
    self.altitude = params.altitude
    self.scales = params.scales
    self.mainCharacterPosX = params.mainCharacterPosX
    self.deadColor = params.deadColor
    self.battleRealStart = false

    self.mapId = params.mapId

    self.isSinglePlayerBattle = true

    self.showMaskLevel = 0 --地图显示黑的层度等级

    self.mapFullBlack = false --地图全黑

    self.hasFullBlackCDBuff = false
    self.isFullBlackSkillRelease = false
    self.isFullBlackSkillReleaseEntityId = 0

    self.isWolfKillTarget = false --自己是否是狼人杀攻击对象

    self.ownerTeamDamageList = {}

    self.targetWarnningSkills = {}

    self.cameraMoveDelay = 0

    self.targetId = 0   -- 表现层当前玩家选择的目标
    self.targetIdFromBattleEngine = 0    -- 引擎底层玩家控制的Unit的当前目标
    self.targetIdOfTarget = 0
    self.entityFactory = EntityFactory.new()
	
	self.myTeamFlower = {}	-- 月影花
	self.partnerNumber = 0	-- 随从个数

    self:enableNodeEvents()

    self.rootLayer = display.newLayer()
    self:addChild(self.rootLayer)

    --角色后背景层，主要用于放置一些特效
    self.backLayer = display.newLayer()
    self.rootLayer:addChild(self.backLayer)

    self.mvpShowLayer = display.newColorLayer(cc.c4b(0,0,0,185))
    self.mvpShowLayer:setContentSize(display.width*16,display.height*2)
    self.mvpShowLayer:setAnchorPoint(cc.p(0,0.5))
    self.mvpShowLayer:setVisible(false)
    self.rootLayer:addChild(self.mvpShowLayer)

    --角色在蒙版后面的层
    self.entityBackLayer = display.newLayer()
	self.rootLayer:addChild(self.entityBackLayer)

    --蒙版层 区分角色 突出角色放该层前面
    -- self.sceneMaskLayer = display.newColorLayer(cc.c4b(255,0,0,100))
    self.sceneMaskLayer = display.newLayer()
    self.sceneMaskLayer:setAnchorPoint(cc.p(0,0))
	self.rootLayer:addChild(self.sceneMaskLayer)

    local fileUtils = cc.FileUtils:getInstance()
    if self.mapId then
        local maskFilePath = string.format("battlefog/Fog_%d.png",tonumber(self.mapId))
        if fileUtils:isFileExist(maskFilePath) then
            local InsetsRect = cc.rect(0,640,2,20)
            local sprite = ccui.Scale9Sprite:create(InsetsRect,maskFilePath)
            sprite:setContentSize(cc.size(display.width*3,display.height*3))
            sprite:setAnchorPoint(cc.p(0,0))
            self.sceneMaskLayer:addChild(sprite)
        end
    end

    --角色在蒙版前面的层
    self.entityLayer = display.newLayer()
	self.rootLayer:addChild(self.entityLayer)

    --屏幕变黑，特别显示的人在这个特殊层上
    self.entitySpecialLayer = display.newLayer()
	self.rootLayer:addChild(self.entitySpecialLayer)

    self.entityWarnningLayer = display.newLayer()
    self.rootLayer:addChild(self.entityWarnningLayer)

    self.entityStatebarLayer = display.newLayer()
    self.rootLayer:addChild(self.entityStatebarLayer)

    --角色对话气泡层
    self.entityBubbleLayer = display.newLayer()
    self.rootLayer:addChild(self.entityBubbleLayer)

    --前景layer
    self.entityFrontLayer = EntityFrontLayer.new()
    self.rootLayer:addChild(self.entityFrontLayer)

    self.effectFactory = EffectFactory.new()
    self.rootLayer:addChild(self.effectFactory)
    self.effectFactory.backLayer = self.backLayer

    self.visualEffect = VisualEffect.new()
    self.rootLayer:addChild(self.visualEffect)
    self.visualEffect.backLayer = self.backLayer
    -- self.visualEffect:addEventListener(VisualEffect.Event_SPAWN_EFFECT,handler(self,BattleController.spawnSkillEffect))
    self.visualEffect:addEventListener(VisualEffect.Event_SKILL_INTERRUPTED,handler(self,BattleController.entitySkillInterrupted))
    self.visualEffect:addEventListener(VisualEffect.Event_SKILL_CANCEL_NO_MANA,handler(self,BattleController.entitySkillCancelByNoMana))

    ----DBM----
    self.dbmMgr = DBMMgr.new()

    --人物触摸层
    self.touchLayer = display.newLayer()
    self.touchLayer:setContentSize(display.width,display.height)
    self.touchLayer:setTouchEnabled(true)
    self.rootLayer:addChild(self.touchLayer)
    self:initTouchLayer(self.touchLayer)

    self.uiLayer = display.newLayer()
    if params.uiLayer then
        params.uiLayer:addChild(self.uiLayer)
    else
        cc.Director:getInstance():getRunningScene():addChild(self.uiLayer)
    end

    self.uiFloatLayer = display.newLayer()
    if params.uiFloatLayer then
        params.uiFloatLayer:addChild(self.uiFloatLayer)
    else
        cc.Director:getInstance():getRunningScene():addChild(self.uiFloatLayer)
    end

    self.splashEffectLayer = display.newColorLayer(cc.c4b(255,0,0,70))
    self.uiLayer:addChild(self.splashEffectLayer)
    self.splashEffectLayer:setVisible(false)

    self.musicPath = self:randomMusic(self.isBossBattle)
    if self.musicPath then
        AM.preload(self.musicPath)
    end

    self.noOperationTime = 15
    self.property = {}

    self.sceneMaskLayer:setVisible(UD.setting:isShowBattleFrog())
    local handle = EM:on("onSettingShowBattleFrog", function(name, isShow)
        self:setFrog(isShow)
    end)
    BattleUIEvent:addEmHandle(handle)
end

function BattleController:initParams()
    local limitLevel = tonumber(GD:getSystemPar("AutoBattleApertureGuideShow",10))
    self.isNeedShowAutoBattleGuideEffect = UD:getPlayer().level < limitLevel
end

function BattleController:initTouchLayer(layer)
    local touchViews = {}
    local function touchBegan(touch, event)
        touchViews = {}
        local locationX,locationY = touch:getLocation2()
        for k,view in pairs(self.views) do
            if cc.isAlive(view) and ((not view:isDead()) or view:getCanRevive()) and view:isVisible() and view:containWorldPoint(locationX,locationY) then
                if not view:isFakeUnit() then
                    self:onShowSelectTarget({targetId = view:getId()})
                end
                --如果不是FakeUnit或者是FakeUnit但是可以交互
                if not view:isFakeUnit() or (view.entityModel and view.entityModel:canInteractWith()) then
                    table.insert(touchViews, view)
                end
            end
        end
        if #touchViews > 0 then
            return true
        else
            return false
        end
    end

    local function touchMoved(touch, event)

    end

    local function touchEnded(touch, event)
        self:onHideSelectTarget(nil)

        local locationX,locationY = touch:getLocation2()
        table.sort(touchViews,function(a,b)
            if cc.isDead(a) or cc.isDead(b) then
                return true
            end
            return a:getLocalZOrder() > b:getLocalZOrder()
        end)

        table.sort(touchViews,function(a,b)
            if cc.isDead(a) or cc.isDead(b) then
                return true
            end
            return a:getBuildingType() > b:getBuildingType()
        end)

        for k,view in pairs(touchViews) do
            if cc.isAlive(view) and ((not view:isDead()) or view:getCanRevive()) and view:isVisible() and view:containWorldPoint(locationX,locationY) then
                -- TODO: 不应该通过表现层数据进行判断
                if not view:isFakeUnit() then
                    view:showTouchEndEffect(true)
                    AM.play(Res.BattleTargetClick, false)
                    local myselfView = self:getControlledView()
                    if myselfView and not myselfView:isAlive() then
                        self:SetMapFocusActor(view)
                    else
                        self:setTarget(view:getId(), true)
                    end
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_CANCEL_AUTO)
                end
                
                if view.entityModel and view.entityModel:canInteractWith() then
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.REALTIME_INTERACTION,{targetId = view:getId(),interactionType = view:getBuildingType()})
                end
                break
            end
        end
    end

    local touchListener = cc.EventListenerTouchOneByOne:create()
    touchListener:registerScriptHandler(touchBegan,cc.Handler.EVENT_TOUCH_BEGAN)
    touchListener:registerScriptHandler(touchMoved,cc.Handler.EVENT_TOUCH_MOVED)
    touchListener:registerScriptHandler(touchEnded,cc.Handler.EVENT_TOUCH_ENDED)
    self:getEventDispatcher():addEventListenerWithSceneGraphPriority(touchListener, layer)

    -- touchListener:setSwallowTouches(true)
end


function BattleController:bindModelEvent(model)

    model:addEventListener(BattleModel.Event_Start,handler(self,BattleController.ready))

    model:addEventListener(BattleModel.Event_GameOver,handler(self,BattleController.onGameOver))

    model:addEventListener(BattleModel.Event_Set_All_UI_Visible,handler(self,BattleController.setAllUIVisible))
    --没用。
    model:addEventListener(BattleModel.Event_Send_Input,handler(self,BattleController.sendInput))

    model:addEventListener(BattleModel.Event_ShowErrorMessage,handler(self,BattleController.showErrorMessage))
    --每帧状态同步。
    model:addEventListener(BattleModel.Event_Sync_Entity_State,handler(self,BattleController.syncEntityState))
    model:addEventListener(BattleModel.Event_Sync_UI_State,handler(self,BattleController.syncUIState))

    model:addEventListener(BattleModel.Event_Fetch_Self_Skills,handler(self,BattleController.fetchSelfSkills))

    model:addEventListener(BattleModel.Event_Sync_Entity_Pos,handler(self,BattleController.syncEntityPos))
    --推出伤害飘字
    model:addEventListener(BattleModel.Event_On_Damage,handler(self,BattleController.onEntityHurt))

    model:addEventListener(BattleModel.Event_UNIT_TALK,handler(self,BattleController.onEntityTalk))

    model:addEventListener(BattleModel.Event_PROJECTILE_BOUNCE,handler(self,BattleController.onProjectileBounce))

    model:addEventListener(BattleModel.Event_UNIT_TEAM_MARK,handler(self,BattleController.onEntityTeamMark))

    model:addEventListener(BattleModel.Event_UNIT_IMMUNE_BUFF,handler(self,BattleController.onEntityImmuneBuff))

    model:addEventListener(BattleModel.Event_UNIT_REVIVE,handler(self,BattleController.onEntityRevive))

    model:addEventListener(BattleModel.Event_SOUL_CHANGED,handler(self,BattleController.onEntitySoulChanged))

    model:addEventListener(BattleModel.Event_Show_BuffDesc,handler(self,BattleController.onShowBuffDesc))

    model:addEventListener(BattleModel.Event_Show_Blind,handler(self,BattleController.onShowBuffBlind))

    model:addEventListener(BattleModel.Event_FirstSend_AutoBattle,handler(self,BattleController.onSetAutoBattle))

    model:addEventListener(BattleModel.Event_FirstSend_KeepBasicAttack,handler(self,BattleController.onSetKeepBasicAttack))

    model:addEventListener(BattleModel.Event_Check_BattleState,handler(self,BattleController.checkBattleState))

    model:addEventListener(BattleModel.Event_SET_NEXT_UPDATE_TIME,handler(self,BattleController.onSetNextUpdateTime))

    model:addEventListener(BattleModel.Event_Enter_Battle,handler(self,BattleController.onEnterBattle))

    model:addEventListener(BattleModel.Event_BATTLE_START,handler(self,BattleController.onBattleStart))

    model:addEventListener(BattleModel.Event_LION_BOSS_APPEAR,handler(self,BattleController.onLionBossAppear))

    model:addEventListener(BattleModel.Event_LION_REFRESH_KILLLIST,handler(self,BattleController.onLionRefreshKillList))

    model:addEventListener(BattleModel.Event_BATTLE_ROUND_PREPARE,handler(self,BattleController.onBattleRoundPrepare))

    model:addEventListener(BattleModel.Event_BATTLE_ROUND_SPACE,handler(self,BattleController.onBattleRoundSpace))

    model:addEventListener(BattleModel.Event_SHOW_TIPS,handler(self,BattleController.onShowTips))

    --dbm
    model:addEventListener(BattleModel.Event_DBM_SKILL_HIT,handler(self,BattleController.onDBMSkillHit))
    model:addEventListener(BattleModel.Event_DBM_ON_HP,handler(self,BattleController.onDBMHp))

    --客户端战斗结束倒计时结束
    model:addEventListener(BattleModel.Event_CLIENT_BATTLE_OVER,handler(self,BattleController.onClientBattleOver))
end

--提示   购买成功失败。。。
function BattleController:onShowTips(event)
    local id = event.unitId
    local tId = event.targetUnitId
    if self.model:getControlledEntityId() == id then
        if event.tipsType == Enums.BattleTipsType.BuyItemSuc then
            display.pushToast(L("meleeNotice1"), Enums.ToastTag.battle)
        elseif event.tipsType == Enums.BattleTipsType.BuyItemFail_Dead then
            if self.model:isMeleeBattle() then
                display.pushToast(L("meleeNotice4"), Enums.ToastTag.battle)
            elseif self.model:isZombieBattle() then
                display.pushToast(L("zombieShopNotice1"), Enums.ToastTag.battle)
            end
        elseif event.tipsType == Enums.BattleTipsType.BuyItemFail_MoneyNotEnough then
            if self.model:isMeleeBattle() then
                display.pushToast(L("meleeNotice3"), Enums.ToastTag.battle)
            elseif self.model:isZombieBattle() then
                display.pushToast(L("zombieShopNotice2"), Enums.ToastTag.battle)
            end
        elseif event.tipsType == Enums.BattleTipsType.BuyItemFail_BuffFull
          or event.tipsType == Enums.BattleTipsType.BuyItemFail_SkillFull then
            display.pushToast(L("meleeNotice2"), Enums.ToastTag.battle)
        elseif event.tipsType == Enums.BattleTipsType.BuyItemFail_MercenaryFull then
            display.pushToast(L("zombieShopNotice3"), Enums.ToastTag.battle)
        elseif event.tipsType == Enums.BattleTipsType.BuyItemFail_SkillInProgress then
            display.pushToast(L("zombieShopNotice4"), Enums.ToastTag.battle)
        end
    end
    if event.tipsType == Enums.BattleTipsType.Kill then
        if self.model:isMeleeBattle()
          or self.model:isPvpBattle()
          or self.model:isGuildWarBattle() then
            local view = self.views[id]
            local entityModel = self:getEntityModelById(view:getUnitModelId())
            if entityModel:isHero() then
                local targetView = self.views[tId]
                local assitsNames = {}
                for _,aid in ipairs(event.assits) do
                    table.insert(assitsNames,self.views[aid]:getName())
                end
                local continuousKill = event.continuousKill or 1

                if continuousKill > 6 then
                    continuousKill = 6
                end

                local data = {icon = view:getCurrentIcon(),name = view:getName(),targetName = targetView:getName(), continuousKill = continuousKill,
                                targetIcon = targetView:getCurrentIcon(),bEnemy = targetView:isEnemy(),assitsNames = assitsNames}

                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SHOW_KILL_TIPS, data)
            end
        end
    elseif event.tipsType == Enums.BattleTipsType.RefreshBattle then
        -- 刷新战斗回合数参数使用unitId存储
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_REFRESH_ROUND, id)
    end
end


function BattleController:onDBMSkillHit(event)
    if self.dbmMgr and UD.setting:isShowDBM() then
        self.dbmMgr:onSkillOrBuff(event.skillId, event.targetId)
    end
end

function BattleController:onDBMHp(event)
    if not UD.setting:isShowDBM() then
        return
    end

    local logicEntities = event.logicEntities
    for k,entity in pairs(logicEntities) do
        local kind = Entity.kind(entity)
        if kind == Enums.EntityKind.EKind_Unit then
            if self.dbmMgr then
                --这里要取id为怪物的TID
                local hp = Unit.hp(entity)
                local hpMax = Unit.hpMax(entity)
                local unitNpcId = Unit.npcId(entity)
                self.dbmMgr:onHp(unitNpcId,hp/hpMax * 100)
            end
        end
    end
end

function BattleController:initMainUI()
    self.mNewBattleUIView = UIMainView.new(self.model:getBattleType())
    if cc.isDead(self.uiLayer) or cc.isDead(self.mNewBattleUIView) then
        return
    end
    self.uiLayer:addChild(self.mNewBattleUIView)
    --設置DBM的UI根節點
    self.dbmMgr:setRootNode(self.mNewBattleUIView:getBossFloatTextNode())

    --持续普攻
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.BATTLE_KEEPBKIL,handler(self,BattleController.onSetKeepBasicAttack))
    --自动战斗
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.BATTLE_AUTO, handler(self,BattleController.onUISetAutoBattle))
    --移动
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.PLAYER_MOVE,handler(self,BattleController.onPlayerMove))
    --翻滚
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.PLAYER_ROLL,handler(self,BattleController.onPlayerRoll))
    --逃跑
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.BATTLE_ESCAPE,handler(self,BattleController.onBattleEscape))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.TRAINING_BATTLE_ESCAPE,handler(self,BattleController.onTrainingBattleEscape))
    --技能
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SKILL_SHOWTIPS,handler(self,BattleController.showClassSkillTips))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SKILL_HIDETIPS,handler(self,BattleController.hideFloatClassSkillPanel))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SKILL_SELECT,handler(self,BattleController.onSelectSkill))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SKILL_FINISH_CHANT_CHARGE,handler(self,BattleController.onFinishChantCharge))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.TARGT_LOCK,handler(self,BattleController.onForceLockTarget))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SKILL_EFFECT,handler(self,BattleController.onPointSkillShowEffect))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SKILL_HIDEEFFECT,handler(self,BattleController.onPointSkillHideEffect))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SKILL_RLSEFFECT,handler(self,BattleController.onPointSkillRelesed))
--    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.TARGT_TAB,handler(self,BattleController.onTabTarget))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SKILL_ATTACK,handler(self,BattleController.setAlreadAttack))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.BUY_ITEM,handler(self,BattleController.onBuyItem))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.USE_ITEM,handler(self,BattleController.onUseItem))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.REALTIME_INTERACTION,handler(self,BattleController.interactWithUnit))

    --复活
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.BATTLE_REVIVE,handler(self,BattleController.onBattleRevive))
    --队长标记
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.TARGT_TEAM_MARK,handler(self,BattleController.onTeamMark))
    --喊话
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.PLAYER_TALK,handler(self,BattleController.onPlayerTalk))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.MELEE_FOCUS,handler(self,BattleController.onFocusPos))
    if self.targetLabel then
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_FMTION,self.targetLabel)
    end

    --训练场伤害刷新
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.BATTLE_TRAINING_DAMAGE_REFRESH,handler(self, BattleController.updateTrainingDamages))
end

function BattleController:onScreenBlink(isStart)
    if isStart then
        local hasAction = self.splashEffectLayer:getActionByTag(Enums.CommonActionTag.BattleScreenBlinkAction)
        if not hasAction then
            local action = cc.RepeatForever:create(cc.Blink:create(1,5))
            action:setTag(Enums.CommonActionTag.BattleScreenBlinkAction)
            self.splashEffectLayer:runAction(action)

            self:startScreenSpalshShake()
        end
    else
        self.splashEffectLayer:stopActionByTag(Enums.CommonActionTag.BattleScreenBlinkAction)
        self.splashEffectLayer:setVisible(false)

        self:stopScreenSpalshShake()
    end
end

function BattleController:getBattleUIRootNode()
    if self.mNewBattleUIView then
        return self.mNewBattleUIView
    end
    return nil
end

function BattleController:setAlreadAttack(bAttack)
    self.bAlreadAttack = bAttack
end

function BattleController:isAlreadAttack()
    return self.bAlreadAttack
end

function BattleController:showErrorMessage(event)
    local messageBox = display.newMessageBox(event.message)
    self:addChild(messageBox)
end

function BattleController:showFloatClassSkillPanel(classSkillId,xrate,yrate)
    --todo
    if not self.mFloatClassSkillView then
        local params = {
            itemId = classSkillId,
            tipsType = Enums.TipsType.classSkill,
            posX = display.width * xrate,
            posY = display.height * yrate,
            anchorX = 0.5,
            anchorY = 0.0,
        }
        self.mFloatClassSkillView = newFloatTipsView.new( params )
        self.uiFloatLayer:addChild(self.mFloatClassSkillView)
    end
end

function BattleController:hideFloatClassSkillPanel()
    if self.mFloatClassSkillView then
        self.mFloatClassSkillView:removeFromParent()
        self.mFloatClassSkillView = nil
    end
end

function BattleController:showClassSkillTips(event)
    local classSkillId = event.classSkillId
    self:showFloatClassSkillPanel(classSkillId,0.5,0.5)
end

function BattleController:exitBattle()
    if self.model then
        self.model:exitBattle()
    end
end

local lastTime = 0
local nowTime = 0
local deltaTime = 0
function BattleController:syncEntityPos(event)
    local logicEntities = event.logicEntities
    local accumulator = event.accumulator
    local isRealStart = event.isRealStart
    local currentEngineTime = event.time
    local dt = event.dt
    local myId = self.model:getControlledEntityId()
    local beforePos = 0
    nowTime = app:getUTCTime()
    deltaTime = nowTime - lastTime
    lastTime = nowTime

    for k,entity in pairs(logicEntities) do
        local id = Entity.getId(entity)
        local kind = Entity.kind(entity)
        local view
        if kind == Enums.EntityKind.EKind_Unit then
            view = self.views[id]
            if view then
                beforePos = view._currentPositionX
                if self:isFastForward() and deltaTime > 1 then
                    local targetX = LocationConfig:getPosOnEntityLayer(Entity.pos(entity))
                    view:setX(targetX)
                elseif Unit.isStartState(entity) then
                    local targetX = LocationConfig:getPosOnEntityLayer(Entity.pos(entity))
                    view:setX(targetX)
                elseif Unit.isMoveState(entity) then
                    local pos = Unit.calMovePos(entity, accumulator)
                    local targetX = LocationConfig:getPosOnEntityLayer(pos)
                    -- view:setX(targetX)
                    view:setTargetX(targetX)
                    view:updatePos(deltaTime)
                    view:setY(0)
                    -- if id == myId then
                    --     local nowSpeed = math.abs(beforePos-view._currentPositionX) / deltaTime
                    --     print("==> move delta:"..math.abs(beforePos-view._currentPositionX), "s:"..nowSpeed, "dt:"..deltaTime, "ET:"..currentEngineTime, "acc:"..accumulator, 
                    --       "isRewind:"..tostring(self:isRewind()), "isFastForward:"..tostring(self:isFastForward()), "nowTime:"..nowTime)
                    -- end
                elseif Unit.isRestrictedState(entity) then
                    if Unit.getRestrictedBuffEffect(entity) == Enums.BuffEffectsLogic.BE_Fear then
                        local pos = Unit.calMovePos(entity, accumulator)
                        local targetX = LocationConfig:getPosOnEntityLayer(pos)
                        view:setX(targetX)
                    elseif Unit.getRestrictedBuffEffect(entity) == Enums.BuffEffectsLogic.BE_Banish
                      and Unit.isManualMoving(entity) then
                        local pos = Unit.calMovePos(entity, accumulator)
                        local targetX = LocationConfig:getPosOnEntityLayer(pos)
                        view:setX(targetX)
                    else
                        local targetX = LocationConfig:getPosOnEntityLayer(Entity.pos(entity))
                        view:setX(targetX)
                    end
                elseif Unit.isIdleState(entity) then
                    local positionX = LocationConfig:getPosOnEntityLayer(Entity.pos(entity))
                    -- if id == myId then
                    --     local nowSpeed = math.abs(positionX-view._currentPositionX) / deltaTime
                    --     print("==> idle delta:"..math.abs(positionX-view._currentPositionX), "s:"..nowSpeed, "dt:"..deltaTime, "ET:"..currentEngineTime, "acc:"..accumulator, 
                    --       "isRewind:"..tostring(self:isRewind()), "isFastForward:"..tostring(self:isFastForward()), "nowTime:"..nowTime)
                    -- end
                    view:setX(positionX)
                    view:setY(0)
                else
                    local skill = Unit.trackSkillInProgress(entity)
                    if skill then
                        local pos = Unit.calTrackPos(entity, skill, accumulator)
                        local trackType = skillInterface.getTrackType(skill)
                        local targetX = LocationConfig:getPosOnEntityLayer(pos)
                        view:setX(targetX)
                        view:setY(self:calcTrackPosy(entity, trackType))
                    else
                        skill = Unit.skillInHitMoveProgress(entity)
                        if skill then
                            local pos = skillInterface.calHitMovePos(skill, accumulator)
                            local targetX = LocationConfig:getPosOnEntityLayer(pos)
                            view:setX(targetX)
                        else
                            skill = Unit.skillInChanneling(entity)
                            if skill and Skill_getChannelCanMove(skill) then
                                -- local pos = Unit.calMovePos(entity, accumulator)
                                -- local targetX = LocationConfig:getPosOnEntityLayer(pos)
                                -- view:setTargetX(targetX1)
                                -- view:updatePos(deltaTime)
                                local targetX = LocationConfig:getPosOnEntityLayer(Entity.pos(entity))
                                view:setX(targetX)
                            end
                        end
                    end
                    view:setY(0)
                end
                if id == myId then
                    local nowSpeed = math.abs(beforePos - view._currentPositionX) / deltaTime
                    local map = MapManager:getMap()
                    local cameraDelta = math.abs(map:getCameraAndFocusBattleActorDelta())
                    -- print("==> move speed:"..nowSpeed, "cameraDelta:"..cameraDelta)
                    if nowSpeed > 0 then
                        if cameraDelta > Constant.BattleCameraSpeedChangeDeltaThreshold then
                            map:setMapAdjustSpeed(nowSpeed * Constant.BattleCameraSpeedChangeFactor)
                        else
                            map:setMapAdjustSpeed(nowSpeed)
                        end
                    else
                        map:setMapAdjustSpeed(Constant.BattleCameraDefaultSpeed)
                    end
                end
            end
        elseif kind == Enums.EntityKind.EKind_Projectile then
            view = self.projectileViews[id]
            if view then
                local pos = Projectile_calMovePos(entity, accumulator - view:getAccumulator()) --entity:calMovePos(accumulator)
                local targetX = LocationConfig:getPosOnEntityLayer(pos)
                -- local speed = Projectile_speed(entity) --entity:speed()
                local projectilePosX = self.entityLayer:toWorldPosition(targetX,0)
                view:update(projectilePosX)
            end
        end
    end
end

function BattleController:setTime(time)
    --time 毫秒
    local gameLength = self.model:getGameLength()
    if self.model:isBattleTimeCountDown() then
        time = math.max(gameLength - time, 0)
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_TIME,time)
    end
end

function BattleController:calcTrackPosy(entity, trackType)
    --曲线算法  草
    if trackType == 0 then
        return 0
    elseif trackType == 1 then
        local dis =  Unit.getTrackTotalDistance(entity)
        local due =  Unit.getTrackCurrentDistance(entity)
        local per =  math.abs(due/dis)>1 and 1 or math.abs(due/dis)
        local delPercent = dis == 0 and 0 or math.abs(0.5 - math.abs(0.5-per))
        local deltaY = LocationConfig:getWidthOnEntityLayer(delPercent * Constant.BattleTrackYMax)
        return deltaY
    end
    return 0
end

function BattleController:updatePvpUI(logicEntities)
    local model = self.model
    if model:isPvpBattle() then
        local myTeamReviveTimes = -1 --是否可以复活自己次数 -1 表示无需复活，还活着/刚死没满2秒
        local controlledEntityId = model:getControlledEntityId()
        for k, entity in pairs(logicEntities) do
            local id = Entity.getId(entity)
            if id == controlledEntityId and Unit.isCanShowPvpReviveUI(entity) then
                myTeamReviveTimes = Unit.getLeftReviveTimes(entity)
                break
            end
        end

        --剩余复活次数
        local leftReviveTimes = model:getLeftReviveTimes(model:getMyTeamId())
        local rightReviveTimes = model:getLeftReviveTimes(model:getEnemyTeamId())
        --击杀次数
        local leftKillTimes = model:getDeadTimes(model:getEnemyTeamId())
        local rightKillTimes = model:getDeadTimes(model:getMyTeamId())
        --print("===========leftReviveTimes:",leftReviveTimes)
        --print("===========rightReviveTimes:",rightReviveTimes)

        --print("===========leftKillTimes:",leftKillTimes)
        --print("===========rightKillTimes:",rightKillTimes)

        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_PVP_FEFRESH_TOP,{leftReviveTimes = leftReviveTimes, rightReviveTimes = rightReviveTimes, leftKillTimes = leftKillTimes, rightKillTimes = rightKillTimes})

        --复活提示
        --需要复活且有复活次数
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_SHOW_PVP_REVIVE,{reviveSelfTimes = myTeamReviveTimes })
    end
end

function BattleController:getLoopApplyTime(skill)
    return Skill_loopApplyTime(skill)
end

--刷新伤害排行
function BattleController:updateDamages(ownerTeamDamageList,controlledEntityId)
    if not self.rankCountTime or self.rankCountTime>30 then
        if self.rankCountTime then
            self.rankCountTime = 0
        else
            self.rankCountTime = 29
        end
    end
    self.rankCountTime = self.rankCountTime+1

    if self.rankCountTime == 30 then
        self.rankData = {}
        for k,data in pairs(ownerTeamDamageList) do
            table.insert(self.rankData,data)
        end
        table.sort(self.rankData,function(l,r)
            return l.value > r.value
        end)

        for i,v in ipairs(self.rankData) do
            v.rank = i
            v.percent = math.floor(100*v.value/self.rankData[1].value)
        end
        app:sendMsg("IMSimpleController", "updateRanks",self.rankData)
    end
end

--训练场伤害计算
function BattleController:updateTrainingDamages()
    local data = {}
    for k,v in pairs(self.ownerTeamDamageList) do
        table.insert(data, v)
    end
    table.sort(data,function(l,r)
        return l.value > r.value
    end)

    for i,v in ipairs(data) do
        v.rank = i
        v.percent = math.floor(100*v.value / data[1].value)
    end
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_TRAINING_SEND_DAMAGE, data)
end

function BattleController:fetchSelfSkills()
    self._skillUIDirty = true
end

--更新战斗表现
function BattleController:syncEntityState(event)
    if self.isGameOver then
        return
    end

    local targetProgress = event.targetProgress
    local condType
    local currentProgressValue
    local targetValue
    if targetProgress then
        condType = targetProgress:getType()
        currentProgressValue = targetProgress:getCurrentValue()
        targetValue = targetProgress:getTargetValue()
    end
    local battleModel = self.model
    local battleLoop = battleModel.mBattleLoop
    local controlledEntityId = battleModel:getControlledEntityId()
    local controlledEntityData = battleLoop:getEntityById(controlledEntityId)

    local logicEntities = event.logicEntities
    local time = event.time
    local accumulator = event.accumulator
    local isRealStart = event.isRealStart
    local leftEscapeTime = event.leftEscapeTime

    local ownerTeamDamageList = self.ownerTeamDamageList

    local uiView = self.mNewBattleUIView
    --技能目标上的警告
    local targetWarnningSkills = self.targetWarnningSkills
    --清理table
    for k,v in pairs(targetWarnningSkills) do
        targetWarnningSkills[k] = nil
    end

    if not self.battleRealStart and isRealStart then
        self.battleRealStart = isRealStart
        --self.mBattleUIView:onBattleRealStart()
    end

    if time and accumulator then
        --self.mBattleUIView:setTime(time + accumulator)
        self:setTime(time + accumulator)
    end

    local views = self.views
    local projectileViews = self.projectileViews

    for _,view in pairs(views) do
        view:setShouldRemove(true)
    end

    for _,projectileView in pairs(projectileViews) do
        projectileView:setShouldRemove(true)
    end

    local showMaskLevel = 0
    local isShowComboEffect = false
    self.showCanBreak = false
    local showTargetsIdList

    local keepShakeId = 0

    local selfBasicSkillTargetId
	
	local lvTeamFlower = self.myTeamFlower
	local lvMoonFlowerCount = 0
	self.partnerNumber = 0
	
    local hasFullBlackCDBuff = false
    local isFullBlackSkillRelease = false
    local isWolfKillTarget = false	
    for _, entity in pairs(logicEntities) do
        local id = Entity.getId(entity)
        local kind = Entity.kind(entity)
        local targetX = LocationConfig:getPosOnEntityLayer(Entity.pos(entity))

        local view
        if kind == Enums.EntityKind.EKind_Unit then
            view = views[id]
            if view then
                if battleModel:isKofBattle() then
                    --决斗之王换人
                    --使用对比unitModelId的方式判断是否还是同一个人
                    local unitModelId = Unit.unitModelId(entity)
                    local currentModelId = view:getUnitModelId()
                    if unitModelId ~= currentModelId then
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, view, false)
                        view:onDeadEnd(true,0.0)
                        local teamId = Entity.teamId(entity)
                        local newEntityModel = clone(self:getEntityModelById(unitModelId))

                        --刷新技能
                        local isMyself = id == controlledEntityId
                        if isMyself then
                            self:initSkillPanel(newEntityModel, id)
                            battleModel:resetMySkills()
                        end

                        local dir = Entity.getInitFace(entity)
                        if dir == Enums.Face.left then
                            --面朝左
                            dir = -1
                        elseif dir == Enums.Face.right then
                            --面朝右
                            dir = 1
                        end
                        newEntityModel:setId(id)
                        newEntityModel:setDir(dir)
                        newEntityModel:setTeamId(teamId)
                        view = self:createViewInBattle(newEntityModel)
                        view:setX(targetX)
                        views[id] = view
                        local isLeft = view:isLeft()
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD, isLeft)
                    end
                else
                    if entity:getIsTransforming() then
                        entity:resetIsTransforming()
                        local isCurrentPlayerTarget = false
                        if id == self.targetId then
                            isCurrentPlayerTarget = true
                            self:clearTarget(false)
                        end
                        view:onDeadEnd(true,0.0)

                        local unitModelId = Unit.unitModelId(entity)
                        local newEntityModel = clone(self:getEntityModelById(unitModelId))

                        local lastUnitModelId = Unit.getLastUnitModelId(entity)
                        local lastEntityModel = self:getEntityModelById(lastUnitModelId)
--                        newEntityModel:setKind(lastEntityModel:getKind())
--                        newEntityModel:setNpcKind(lastEntityModel:getNpcKind())
                        newEntityModel:setIsLeader(lastEntityModel:getIsLeader())
                        newEntityModel:setCanRevive(lastEntityModel:getCanRevive())
                        newEntityModel:setRelatedNpcId(lastEntityModel:getRelatedNpcId())

                        --刷新技能
                        local isMyself = id == controlledEntityId
                        if isMyself then
                            self:initSkillPanel(newEntityModel, id)
                            battleModel:resetMySkills()
                        end

                        local dir = Entity.getInitFace(entity)
                        if dir == Enums.Face.left then
                            --面朝左
                            dir = -1
                        elseif dir == Enums.Face.right then
                            --面朝右
                            dir = 1
                        end
                        local teamId = Entity.teamId(entity)
                        newEntityModel:setId(id)
                        newEntityModel:setDir(dir)
                        newEntityModel:setTeamId(teamId)
                        view = self:createViewInBattle(newEntityModel)
                        view:setX(targetX)
                        views[id] = view
                        local isLeft = view:isLeft()
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD, isLeft)
                        if isCurrentPlayerTarget then
                            self:setTarget(id, false)
                        end
                    end
                end
                view:setShouldRemove(false)
				
				local unitNpcId = Unit.npcId(entity) 
				if view and Unit.isSummon(entity) and (not view:isEnemy()) and (unitNpcId == Constant.Zombies_Moon_Flower_NPC_ID) then
					lvMoonFlowerCount = lvMoonFlowerCount + 1
				end
            else
                if (not Entity.deceased(entity)) and (not Entity.shouldRemove(entity)) then
                    --创建新的Unit表现
                    local dir = Entity.getInitFace(entity)
                    if dir == Enums.Face.left then
                        --面朝左
                        dir = -1
                    elseif dir == Enums.Face.right then
                        --面朝右
                        dir = 1
                    end
                    local teamId = Entity.teamId(entity)
                    local unitNpcId = Unit.npcId(entity)
                    local entityModel
                    if Unit.isSummon(entity) then
                        --如果是召唤怪
                        if Unit.isSummonerClone(entity) then
                            local unitModelId = Unit.unitModelId(entity)
                            entityModel = clone(self:getEntityModelById(unitModelId))
                            entityModel:setId(Entity.getId(entity))
                            entityModel:setIsSummonEntity(true)
                            entityModel:setIsFakeNpc(true)
                            entityModel:setCanRevive(false)
                        else
                            entityModel = clone(self:getSummonEntityModelByNpcId(unitNpcId))
                        end
                    else
                        --如果是刷新怪
                        local unitModelId = Unit.unitModelId(entity)
                        entityModel = clone(self:getEntityModelById(unitModelId))
                        entityModel:setId(Entity.getId(entity))
                        entityModel:setIsRefreshEntity(Unit.isRefresh(entity))
                    end

                    if entityModel ~= nil then
                        entityModel:setId(id)
                        entityModel:setDir(dir)
                        entityModel:setTeamId(teamId)
                        view = self:createViewInBattle(entityModel)
                        view:setX(targetX)
						
						-- 己方月影花数量 begin															
						if view and Unit.isSummon(entity) and (not view:isEnemy()) then							
							if unitNpcId == Constant.Zombies_Moon_Flower_NPC_ID then															
								local lvSummId = Unit.getSummonerId(entity)						
								for k, v in ipairs(lvTeamFlower) do
									if k == lvSummId then
										v.flowerCount = v.flowerCount + 1
										lvMoonFlowerCount = lvMoonFlowerCount + 1
										break
									end
								end																													
							end							
						end
						-- 己方月影花数量 end
                    end									
                end							
            end	
			
			-- 获取随从数量
			if view and Unit.isSummon(entity) and (not view:isEnemy()) then
				self.partnerNumber = self.partnerNumber + 1
			end				
        elseif kind == Enums.EntityKind.EKind_Projectile then
            view = projectileViews[id]
            if view then
                view:setShouldRemove(false)
            else
                --创建新的Projectile表现
                local casterId = Projectile_getCasterId(entity)
                local targetId = Projectile_getTargetId(entity)
                local casterView = views[casterId]
                local targetView
                local targetPoint
                if targetId > 0 then
                    targetView = views[targetId]
                else
                    targetPoint = LocationConfig:getPosOnEntityLayer(entity:getTargetPoint())
                end

                if casterView and (targetView or targetPoint) then
                    local projectileConfig = Projectile_cfg(entity)
                    local objectId = ProjectileConfig_getObjectId(projectileConfig)
                    local objectConfig = battleModel:getObjectConfig(objectId)

                    -- effectfactory create projectile
                    if objectConfig then
                        view = self.effectFactory:createEffect(casterView, targetView, targetPoint, projectileConfig, objectConfig)
                        projectileViews[id] = view
                        local projectilePosX = self.entityLayer:toWorldPosition(targetX,0)
                        view:fire(projectilePosX, true)
                        view:setAccumulator(accumulator)
                    end
                end
            end
        elseif kind == Enums.EntityKind.EKind_Settlement then
            -- TODO:
        end

        if not view then
            if (not Entity.deceased(entity)) and (not Entity.shouldRemove(entity)) then
--                printError("WARN: cannot create entity view:"..id)
            end
        else
            if kind == Enums.EntityKind.EKind_Unit then
                if not hasFullBlackCDBuff and Unit.hasBuffTag(entity, Constant.BattleScreenBlackBuffTag) then
                    hasFullBlackCDBuff = true
                end
                local isSelfTeam = view:isSelfTeam()

                -- 隐身状态表现
                local flagInCompleteStealth = Unit.isInCompleteStealth(entity)
                local flagInStealth = Unit.isInStealth(entity)
                local flagInDisguise = Unit.isInDisguise(entity)
                if flagInCompleteStealth then
                    if view:enterStealth() then
                        local isLeft = view:isLeft()
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD,isLeft)
                    end
                elseif not isSelfTeam and (flagInStealth or flagInDisguise) then
                    if view:enterStealth() then
                        local isLeft = view:isLeft()
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD,isLeft)
                    end
                elseif (flagInStealth or flagInDisguise) then
                    view:setOpacity(Constant.BattlePalEntityStealthOpacity)
                    view:show()
                else
                    if view:leaveStealth() then
                        local isLeft = view:isLeft()
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD,isLeft)
                    end
                    view:setOpacity(255)
                    view:show()
                end

                view:turn(Entity.face(entity))

                local hp = Unit.hp(entity)
                local hpMax = Unit.hpMax(entity)
                view:setHpProgress(hp,hpMax,false)

                local shouldHideAllHpUIFlag = Unit.shouldHideAllHpUI(entity)
                if battleModel:isKofBattle() then
                    -- 屏蔽召唤怪，因为 法师的 召唤镜像，使用的entitymodel 是 玩家的 entitymodel，其uid与玩家uid一致，造成bug
                    if not view:isSummon() then
                        local entityModel = self:getEntityModelById(view:getUnitModelId())
                        local uid = entityModel:getUid()
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_KOF_HP_UPDATE,{uid = uid, hp = hp, hpMax = hpMax})
                        -- 刷新血条可见性
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_KOF_HP_HIDE, shouldHideAllHpUIFlag)
                    end
                end

                local markId = Unit.getFlag(entity)
                view:setTeamMarkId(markId)

                local hurtTime = Entity.hurtTime(entity)

                local speed = Unit.speed(entity)
                local baseSpeed = Unit.baseSpeed(entity)
                view:setMoveSpeed(speed,baseSpeed)

                view:refreshBuffs(entity)

                local mana = Unit.mana(entity)
                local manaMax = Unit.manaMax(entity)

                local rage = Unit.rage(entity)
                local rageMax = Unit.rageMax(entity)

                local newEnergy = Unit.energy(entity)
                local newEnergyMax = Unit.energyMax(entity)

                local comboPoint = Unit.comboPoint(entity)
                local comboPointMax = Unit.comboPointMax(entity)

                view:setStar(comboPoint,comboPointMax)

                view:setManaProgress(mana,manaMax)

                local isSelf = id == controlledEntityId

                if isSelf then
                    self.property = {mana = mana,rage = rage,energy = newEnergy}
                end

                if view:isHero() and battleModel:isMeleeBattle() then
                    local miniSkillView = view:getMiniSkillView()
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_SKILL,miniSkillView,entity:getBuyedItemsByType(Enums.ShopItemType.Skill),entity)
                end

                if view:isDead() and (battleModel:isMeleeBattle() or battleModel:isZombieBattle()) then
                    if view:getPlayerNode() then
                        view:getPlayerNode():setCD(entity:getReviveTime(),entity:getReviveIntervalTime())
                    end
                else
                    if view:getPlayerNode() then
                        view:getPlayerNode():hideCD()
                    end
                end

                local buffList = view:getBuffIconDict()

                if buffList then
                    if isSelf then
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BUFF_SELT,buffList,id)
                    end
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BUFF_UPDATE,buffList,id)
                end
                -- 刷新血条可见性
                view:shouldHideAllHpUI(shouldHideAllHpUIFlag)

                if isSelf then
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_COMBO,comboPoint)
                    local skillRoll = Unit.skillRoll(entity)
                    if skillRoll then
                        local cd = Skill_cd(skillRoll)
                        local percent = cd / Skill_cdD(skillRoll) * 100
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_ROLLCD, "mainui", true, percent, cd)
                    end
                end

                if isSelf then
                    if not isWolfKillTarget and Unit.hasBuffTag(entity, Constant.BattleScreenAttackWolfKill) then
                        isWolfKillTarget = true
                    end

                    --todo
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.STATUS_MANA,mana,manaMax,rage,rageMax,newEnergy,newEnergyMax)
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.STATUS_HP,hp,hpMax)
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.STATUS_HP_HIDE, shouldHideAllHpUIFlag )

                    selfBasicSkillTargetId = Unit.getNextBasicTargetId(entity)
                    --引擎层目标切换时
                    if self.targetIdFromBattleEngine ~= selfBasicSkillTargetId then
                        if self.targetId ~= selfBasicSkillTargetId then
                            local targetView = views[selfBasicSkillTargetId]
                            if targetView then
                                if targetView:isAlive() then
                                    self:setTarget(selfBasicSkillTargetId, false)
                                elseif targetView:getCanRevive() and targetView:isHero() then
                                    self:setTarget(selfBasicSkillTargetId, false)
                                else
                                    self:clearTarget(false)
                                end
                            else
                                self:clearTarget(false)
                            end
                        end
                        self.targetIdFromBattleEngine = selfBasicSkillTargetId
                    end

                    --同步逻辑目标强制锁定
                    local isTargetForceLocked = Unit.isLockSkillTarget(entity)
                    self:setForceTargetLockedFlag(isTargetForceLocked)
                end

                local buffList
                local isCurrentPlayerTarget = view:getIsCurrentPlayerTarget()
                local targetIdOfTarget
                -- NOTE: 接下来的判断顺序暗示了表现的优先级关系
                if Unit.dead(entity) then
                    -- 死亡状态
                    if isSelf then
                        view:playReadyReleaseSkill(false)
                    end
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, view, false)
                    if isSelf then
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, "mainui", false)
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_ROLLCD, "mainui", false)
                    end
                    view:perform(Enums.CharacterState.dead)
                    if isCurrentPlayerTarget then
                        self:clearTarget(true)
                    end
                elseif Unit.restricted(entity) then
                    -- 限制状态
                    if isSelf then
                        view:playReadyReleaseSkill(false)
                    end
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, view, false)
                    if isSelf then
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, "mainui", false)
                    end
                    -- local buffEffect = Unit.getRestrictedBuffEffect(entity)
                    local buffEffects = Unit.getAllRestrictedSkillBuffEffects(entity)
                    local fallTime = Entity.fallTime(entity)
                    view:perform(Enums.CharacterState.restricted, {buffEffects = buffEffects, t = time + accumulator, fallTime = fallTime, entity = entity})
                else
                    if isSelf then
                        local superSkillPreProgress = Unit.superSkillPreProgress(entity) --entity:superSkillPreProgress()
                        if superSkillPreProgress then
                            view:playReadyReleaseSkill(true)
                        else
                            view:playReadyReleaseSkill(false)
                        end
                    end

                    local skill = Unit.skillInProgress(entity)
                    if not skill then
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, view, false)
                        if isSelf then
                            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, "mainui", false)
                        end
                        if isCurrentPlayerTarget then
                            targetIdOfTarget = 0
                        end
                    end

                    if skill then
                        local skillId = skillInterface.id(skill) --skill:name()
                        if not isFullBlackSkillRelease and skillId == Constant.BattleScreenBlackSkillId then
                            isFullBlackSkillRelease = true
                            self.isFullBlackSkillReleaseEntityId = id
                        end
                        -- print("----skill------")
                        local skillName = Skill_name(skill) --skill:name()

                        local applied = Skill_appliedPreReleaseFinish(skill)
                        local isBasicSkill = Skill_isBasicAttack(skill) --skill:isBasicAttack()

                        local isShowScreenMask = false
                        local applyTime = Skill_applyTime(skill)

                        if isCurrentPlayerTarget then
                            targetIdOfTarget = Skill_targetId(skill)
                        end

                        -- if isSelf then
                            isShowScreenMask = skillInterface.getIsShowScreenMask(skill)
                        -- end
                        if (not isBasicSkill) then
                            if isSelf then
                                --如果是自己释放技能
                                if isShowScreenMask and not skillInterface.isChanneled(skill) then
                                    showTargetsIdList = self:getSkillTargets(skill)
                                end

                                if isShowScreenMask then
                                    showMaskLevel = 2
                                end

                                local isComboSkill = skillInterface.isComboSkill(skill)
                                if isComboSkill then
                                    isShowComboEffect = true
                                end
                                -- isShowMask = true
                            else
                                --print("===========showMaskLevel",showMaskLevel)
                                --print("===========showMaskLevel 111",skill:id())
                                if (not isSelfTeam) and (showMaskLevel == 0) then
                                    if isShowScreenMask then
                                        --print("===========showMaskLevel",showMaskLevel)
                                        showMaskLevel = 1
                                    end
                                end
                            end
                        else
                            if isSelf then
                                --自己的普攻技能
                                selfBasicSkillTargetId = Skill_targetId(skill)
                            end
                        end

                        -- if (not isBasicSkill) and applied then
                        if applied then
                            local startTime = applyTime
                            if skill:getChannelType()==Enums.ChannelType.ChannelType_Loop then
                                startTime = self:getLoopApplyTime(skill)
                            end


                            -- local totalTime = Skill_chantD(skill) --[[skill:chantD()]] + Skill_channelD(skill)--[[skill:channelD()]] + Skill_releaseD(skill)--[[skill:releaseD()]]
                            local totalTime = Skill_chantD(skill) --[[skill:chantD()]] + Skill_channelD(skill)--[[skill:channelD()]]
                            local currentTime = time + accumulator - startTime --[[skill:applyTime()]]
                            --print("totalTime:",totalTime)
                            --print("currentTime:",currentTime)
                            local precent = math.floor(100*currentTime/totalTime)
                            local canBeBrokenByAccDamage = skillInterface.canBeBrokenByAccDamage(skill)
                            local accDamagePercent
                            local isSpecialBrokenType
                            local beBrokenAccDamageMax

                            if canBeBrokenByAccDamage then
                                isSpecialBrokenType = SkillConfig_isSpecialBrokenType( Skill_cfg(skill) )
                                beBrokenAccDamageMax = skillInterface.getBeBrokenAccDamageMax(skill)
                                accDamagePercent = math.floor(100*skillInterface.getBeBrokenAccDamage(skill)/beBrokenAccDamageMax)
                            end

                            if totalTime > 0 and (Skill_isChantSkill(skill) or skillInterface.isChanneled(skill)) and not isBasicSkill then
                                local bShow = true
                                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS,view,bShow,L(skillName),precent, accDamagePercent, isSpecialBrokenType, beBrokenAccDamageMax)
                                if not isSelf then
                                    bShow = false
                                end
                                if isSelf then
                                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS,"mainui",bShow,L(skillName),precent)
                                end
                                if view:getPlayerNode() then
                                    view:getPlayerNode():setSkillBar(precent)
                                end
                            else
                                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, view, false)
                                if isSelf then
                                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, "mainui", false)
                                end
                                if view:getPlayerNode() then
                                    view:getPlayerNode():setSkillBar(0)
                                end
                            end
                        end

                        if Skill_duringReleaseRecover(skill) --[[skill:duringReleaseRecover()]] then
                            -- view:skill(skillName)
                            view:perform(Enums.CharacterState.skill, skill)
                        elseif Skill_duringChanting(skill) --[[skill:duringChanting()]] then
                            -- view:chant(skillName)
                            view:perform(Enums.CharacterState.chant, skill)
                            if Skill_getIsMarkTarget(skill) then
                                table.insert(targetWarnningSkills, skill)
                            end
                            local shakeId = Skill_getKeepShake(skill)
                            if shakeId > 0 then
                                if view:isCanPlayShake() then
                                    keepShakeId = shakeId
                                end
                            end
                        elseif Skill_duringTracking(skill) then
                            view:perform(Enums.CharacterState.track, skill)
                            local shakeId = Skill_getKeepShake(skill)
                            if shakeId > 0 then
                                if view:isCanPlayShake() then
                                    keepShakeId = shakeId
                                end
                            end
                        elseif Skill_duringChanneling(skill) --[[skill:duringChanneling()]] then
                            -- view:perform(Enums.CharacterState.channel, skill)
                            -- print("-----------------skill:duringChanneling()--------------")
                            local currentSkillKey = Skill_uid(skill)..applyTime
                            local isCurrentSkillCached = self.skillTargetIdListCacheKey == currentSkillKey
                            if isCurrentSkillCached then
                                showTargetsIdList = self.skillTargetIdListCache
                            end

                            local subSkill = Skill_currentSubSkill(skill) --skill:currentSubSkill()
                            if subSkill then
                                if (not isBasicSkill) and isShowScreenMask and isSelf then
                                    --如果是自己释放技能
                                    showTargetsIdList = self:getSkillTargets(subSkill)
                                    if not isCurrentSkillCached then
                                        self.skillTargetIdListCacheKey = currentSkillKey
                                        self.skillTargetIdListCache = showTargetsIdList
                                    else
                                        if (not showTargetsIdList) or (#showTargetsIdList == 0) then
                                            showTargetsIdList = self.skillTargetIdListCache
                                        end
                                    end
                                end

                                -- print("-----------------subSkill-------------")
                                -- print("-------subSkill:",subSkill:getState())
                                if Skill_duringReleaseRecover(subSkill) --[[subSkill:duringReleaseRecover()]] then
                                    -- print("-----------------subSkill:duringReleaseRecover()-------------")
                                    view:perform(Enums.CharacterState.skill, subSkill)
                                elseif Skill_duringChanting(subSkill) --[[subSkill:duringChanting()]] then
                                    -- print("-----------------subSkill:duringChanting()-------------")
                                    view:perform(Enums.CharacterState.chant, subSkill)
                                elseif Skill_duringTracking(subSkill) then
                                    view:perform(Enums.CharacterState.track, subSkill)
                                end

                                if Skill_getIsMarkTarget(subSkill) then
                                    table.insert(targetWarnningSkills, subSkill)
                                end
                            end

                            local shakeId = Skill_getKeepShake(skill)
                            if shakeId > 0 then
                                if view:isCanPlayShake() then
                                    keepShakeId = shakeId
                                end
                            end
                        else
                            view:perform(Enums.CharacterState.idle,{t = time + accumulator, hurtT = hurtTime})
                        end
                    elseif Unit.isMoveState(entity) --[[entity:isMoveState()]] then
                        -- print("----isMoveState------")
                        -- view:move()
                        view:perform(Enums.CharacterState.move)
                    elseif Unit.isHurtState(entity) then
                        view:perform(Enums.CharacterState.hurt, entity)
                    elseif Unit.isIdleState(entity) --[[entity:isIdleState()]] then
                        -- print("----isIdleState------")
                        -- view:idle()
                        -- print("-------------entity:hurtTime():"..entity:hurtTime())
                        view:perform(Enums.CharacterState.idle,{t = time + accumulator, hurtT = hurtTime})
                    elseif Unit.isStartState(entity) then
                        view:perform(Enums.CharacterState.idle,{t = time + accumulator, hurtT = hurtTime})
                    end
                end

                isCurrentPlayerTarget = (id == self.targetId)
                if isCurrentPlayerTarget and uiView.topView then
                    --判断是否要切换目标的目标
                    if targetIdOfTarget and targetIdOfTarget ~= self.targetIdOfTarget then
                        local view_tot = views[targetIdOfTarget]
                        if view_tot then
                            local entityModel = self:getEntityModelById(view_tot:getUnitModelId())
                            uiView.topView.targetView:setDataRight(entityModel,view_tot,targetIdOfTarget,false)
                            self.targetIdOfTarget = targetIdOfTarget
                        else
                            uiView.topView.targetView:setDataRight(nil, nil, nil, false)
                            self.targetIdOfTarget = 0
                        end
                    end
                end

                -- view:processedHurt(time + accumulator,hurtTime)

            elseif kind == Enums.EntityKind.EKind_Projectile then
                --effectfactory create projectile
                view:setDeceased(Entity.deceased(entity) --[[entity:deceased()]])
                -- local speed = Projectile_speed(entity) --entity:speed()
                -- local projectilePosX = self.entityLayer:toWorldPosition(targetX,0)

                local pos = Projectile_calMovePos(entity, accumulator - view:getAccumulator()) --entity:calMovePos(accumulator)
                targetX = LocationConfig:getPosOnEntityLayer(pos)
                -- local speed = Projectile_speed(entity) --entity:speed()
                local projectilePosX = self.entityLayer:toWorldPosition(targetX,0)

                view:update(projectilePosX)

            elseif kind == Enums.EntityKind.EKind_Settlement then

            end
        end
    end
	
	-- 处理月影花的死亡 begin 
	local tempCount = 0
	for	_, v in ipairs(lvTeamFlower) do
		tempCount = tempCount + v.flowerCount
	end
	
	if tempCount > lvMoonFlowerCount then
		local lvDiffer = lvMoonFlowerCount - tempCount
		for	_, v in ipairs(lvTeamFlower) do
			if v.flowerCount > 0 then
				v.flowerCount = v.flowerCount - 1
				lvDiffer = lvDiffer - 1
			end
			
			if lvDiffer == 0 then
				break
			end
		end				
	end	
	-- 处理月影花的死亡 end
	
    local isNeedFullBlack = isFullBlackSkillRelease or hasFullBlackCDBuff

    if self.hasFullBlackCDBuff ~= hasFullBlackCDBuff then
        if hasFullBlackCDBuff then
            uiView:showScreenBlackCDEffect(true)
        else
            uiView:showScreenBlackCDEffect(false)
        end
    end

    if self.hasFullBlackCDBuff ~= hasFullBlackCDBuff or self.isFullBlackSkillRelease ~= isFullBlackSkillRelease or self.isWolfKillTarget ~= isWolfKillTarget then
        --刷新层级
        --狼王 在技能释放的时候置于 特殊层
        for id,view in pairs(views) do
            local isSpecial = false
            if self.isFullBlackSkillReleaseEntityId == id then
                isSpecial = isFullBlackSkillRelease or isWolfKillTarget
            elseif view:isSelf() then
                isSpecial = hasFullBlackCDBuff or isFullBlackSkillRelease
            end
            local isWolfCtrlStatusVisble = (not isSpecial) and isNeedFullBlack
            self:refreshViewLayer(view, isSpecial, isWolfCtrlStatusVisble)
        end

        self.entityBackLayer:setVisible(not isNeedFullBlack)
        self.entityLayer:setVisible(not isNeedFullBlack)

        self.hasFullBlackCDBuff = hasFullBlackCDBuff
        self.isFullBlackSkillRelease = isFullBlackSkillRelease
        self.isWolfKillTarget = isWolfKillTarget
    end

    --如果技能在释放或者有黑屏buff
    if isNeedFullBlack then
        if not self.mapFullBlack then
            self:setMapFullBlack()
        end
    else
        if self.mapFullBlack then
            self:removeMapFullBlack()
        end
    end

    if self.mapFullBlack then
        --todo
    else
        if self.showMaskLevel ~= showMaskLevel then
            if showMaskLevel > 0 then
                self.showMaskLevel = showMaskLevel
                self:showMaskForReleaseEffect(showMaskLevel)
            else
                if not self.isLastEntityActionRun then
                    self:hideMaskForReleaseEffect()
                end
            end
        end
    end

    self:showComboEffect(isShowComboEffect)

    if keepShakeId > 0 then
        local hitShake = ShakeConfig:getConfig(keepShakeId)
        if hitShake then
            self:screenShake(hitShake, Enums.CommonActionTag.BattleScreenShake)
        end
    else
        if self:hasKeepShake() then
            self:stopKeepShake()
        end
    end

    local function removeProjectileView(k)
        projectileViews[k]:removeFromParent()
        projectileViews[k] = nil
    end

    for k,projectileView in pairs(projectileViews) do
        if projectileView:isShouldRemove() then
            projectileView:doDelayRemove(k, removeProjectileView)
        end
    end

    for id,view in pairs(views) do
        if view:isShouldRemove() then
            view:setHpProgress(0,100,false)
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, view, false)
            if view:isSelf() then
                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_PROCESS, "mainui", false)
                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_ROLLCD, "mainui", false)
            end
            view:perform(Enums.CharacterState.dead)
        end

        if view:isDead() then
            if id == self.targetId and uiView.topView then
                uiView.topView.targetView:clearData()
            end
        end

        local outlineType
        if view:isSelf() then
            outlineType = 1
        elseif not view:isSelfTeam() and selfBasicSkillTargetId == id and (not view:isDead() or view:getCanRevive()) then
            outlineType = 2
        elseif view:isSelfTeam() and id == selfBasicSkillTargetId and not view:isDead() then
            outlineType = 3
        end
        view:displayOutlineEffect(outlineType~=nil,outlineType)
        if not view:isHero() then
            view:getPositionX()
            local pos = view:convertToWorldSpace(cc.p(0, 0))

            if math.abs(pos.x-display.width/2) >display.width then
                view:getArmature():setVisible(false)
                --view:getArmature():pauseAni()
            else
                view:getArmature():setVisible(true)
                --view:getArmature():resumeAni()
            end
        end
    end

    local isWarnedForController = false
    for id,actorView in pairs(views) do
        --需要在设置之前判断是否
        if controlledEntityId == id then
            isWarnedForController = actorView:getIsWarned()
        end
        actorView:setWarning(false)
        actorView:setWarningRange(false)
        --self.mBattleUIView:setWarning(id,false)
    end
    self:showScreenWarning(false)
    self:showPointWarning(false)
    self:showTargetWarnning(targetWarnningSkills, isWarnedForController)

    self._currentRealTime = time + accumulator
end

--更新UI表现
function BattleController:syncUIState(event)
    if self.isGameOver then
        return
    end
    local battleModel = self.model
    local battleLoop = battleModel.mBattleLoop
    local controlledEntityId = battleModel:getControlledEntityId()
    local mainUIView = self.mNewBattleUIView

    local logicEntities = event.logicEntities
    local ownerTeamDamageList = self.ownerTeamDamageList
    local controlledEntityModel = battleModel:getControlledEntity()

    --设置逃跑按钮状态
    if not self.notSetEsc then
        if battleLoop:isAfterEscapeTime() then
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_SET_ABLE,true)
            self.notSetEsc = true
        end
    end

    if battleModel:isKofBattle() then
        local leftKofRoundTime = battleLoop:getKofRoundLeftTime()
        local selfTeamIndex
        local enemyTeamIndex
        if battleModel:getMyTeamId() then
            selfTeamIndex = battleLoop:getKofIndexByTeam(battleModel:getMyTeamId()) + 1 --c++层是从0开始，lua是从1开始的
        end
        if battleModel:getEnemyTeamId() then
            enemyTeamIndex = battleLoop:getKofIndexByTeam(battleModel:getEnemyTeamId()) + 1 --c++层是从0开始，lua是从1开始的
        end
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_KOF_UPDATE_DATA,{leftKofRoundTime = leftKofRoundTime, selfTeamIndex = selfTeamIndex, enemyTeamIndex = enemyTeamIndex})
    elseif battleModel:isMeleeBattle() then
        local rightScore, leftScore
        if battleModel:getMyTeamId() then
            leftScore = battleLoop:getScoreByTeamId(battleModel:getMyTeamId())
        end
        if battleModel:getEnemyTeamId() then
            rightScore = battleLoop:getScoreByTeamId(battleModel:getEnemyTeamId())
        end
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_SCORE, leftScore, rightScore)
    elseif battleModel:isTheatrePve() then
        if self._bossEntityIds and #self._bossEntityIds > 0 then
            local curHp, maxHp = 0, 0
            for i, id in ipairs(self._bossEntityIds) do
                local bossEntity = logicEntities[ id ]
                if bossEntity then
                    curHp = curHp + Unit.hp( bossEntity )
                    if not self._theatreBossHpMax then
                        maxHp = maxHp + Unit.hpMax( bossEntity )
                    end
                end
            end

            -- self._theatreBossHpMax 记录第一次不为0的hpMax
            if maxHp ~= 0 then
                self._theatreBossHpMax = maxHp
            end

            local theatreRestLife = battleModel:getLeftReviveTimes( controlledEntityModel.teamId )
            EM:notify("upTheatreBossInfo", curHp, self._theatreBossHpMax, theatreRestLife)
        end
	elseif battleModel:isZombieBattle() then
		-- 更新鱼人商店随从数量
		BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_REFRESH_ZOMBIE_SHOP_TIPS, self.partnerNumber)	
    end
	
    local entityModel
    local isMyself
    local isInMyTeam
	local views = self.views
	local lvTeamFlower = self.myTeamFlower
    self.meleeBattleStatus = self.meleeBattleStatus or {}
    for _, entity in pairs(logicEntities) do
        local id = Entity.getId(entity)
		local view = views[id]
        local kind = Entity.kind(entity)
        if kind == Enums.EntityKind.EKind_Unit then
            entityModel = battleModel:getEntityModelById(Unit.unitModelId(entity))

            isMyself = controlledEntityId == id
            isInMyTeam = entityModel:isInMyTeam()
            local shouldHideAllHpUIFlag = Unit.shouldHideAllHpUI(entity)

            if id == self.targetId and mainUIView.topView then
                local hp = Unit.hp(entity)
                local hpMax = Unit.hpMax(entity)
                local mana = Unit.mana(entity)
                local manaMax = Unit.manaMax(entity)
                local rage = Unit.rage(entity)
                local rageMax = Unit.rageMax(entity)
                local energy = Unit.energy(entity)
                local energyMax = Unit.energyMax(entity)
                local hpExtra = 0
                local hpMaxExtra = 0
                if entityModel:hasRelatedNpc() then
                    -- 关联Entity状态
                    local relatedEntity = self.model.mBattleLoop:getEntityById(Unit.getRelatedNpcUnitId(entity))
                    if relatedEntity then
                        hpExtra = Unit.hp(relatedEntity)
                        hpMaxExtra = Unit.hpMax(relatedEntity)
                    end
                end
                --更新选中框的数据
                mainUIView.topView.targetView:updateData(id, hp, hpMax,
                    mana, manaMax, rage, rageMax, energy, energyMax, hpExtra, hpMaxExtra)
                -- 刷新血条可见性
                mainUIView.topView.targetView:shouldHideAllHpUI(shouldHideAllHpUIFlag)
            end

            if UD.setting:isShowBattleTOT() and id == self.targetIdOfTarget and mainUIView.topView then
                local hp = Unit.hp(entity)
                local hpMax = Unit.hpMax(entity)
                local mana = Unit.mana(entity)
                local manaMax = Unit.manaMax(entity)
                local rage = Unit.rage(entity)
                local rageMax = Unit.rageMax(entity)
                local energy = Unit.energy(entity)
                local energyMax = Unit.energyMax(entity)
                mainUIView.topView.targetView:updateDataRight(id, hp, hpMax,
                    mana, manaMax, rage, rageMax, energy, energyMax)
                -- 刷新血条可见性
                mainUIView.topView.targetView:shouldHideAllHpUIRight(shouldHideAllHpUIFlag)
            end

            if not isInMyTeam and view and view:getPlayerNode() then
                local skill = Unit.skillInProgressCanBreak(entity)
                if skill then
                    if Skill_getCanBeBroken(skill) then
                        view:getPlayerNode():playCanBreak(true)
                        self.showCanBreak = true
                    end
                else
                    view:getPlayerNode():playCanBreak(false)
                    view:getPlayerNode():setSkillBar(0)
                end
            end

            --大乱斗
            if battleModel:isMeleeBattle() and entityModel:isHero() then
                --灵魂强度显示
                view:setSoulCount(Unit.getSoul(entity))
                --先做个人数据统计
                if isMyself then
                    local unitStat = Unit.getUnitStat(entity)
                    local killTimes = UnitStat.getKillPlayerTimes(unitStat)
                    local assistTimes = UnitStat.getAssists(unitStat)
                    local deadTimes = UnitStat.getDeadTimes(unitStat)
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_STATUS,killTimes,assistTimes,deadTimes)
                end
            end
				
			-- 鱼人僵尸 自己这组的月影花数量		
			if battleModel:isZombieBattle() and entityModel:isHero() and isInMyTeam and not Unit.isSummonerClone(entity) then
				local miniSkillView = view:getMiniSkillView()
				local lvUID = entityModel:getUid()
				for _, v in ipairs(lvTeamFlower) do
					if lvUID == v.heroUid then
						if v.flowerCount >= 0 then						
							BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_REFRESH_FLOWER_NODE, miniSkillView, v.flowerCount)		
						end
					end
				end
			end
			
            --如果不是单人战斗，需要统计本队伤害排名
            --训练场战斗模式下，全部统计伤害值 2018.12.12
            if battleModel:isTraining() then
                if isInMyTeam and entityModel:isHero() and not entity:isSummon() and not Unit.isSummonerClone(entity) then
                    local unitStat = Unit.getUnitStat(entity)
                    if ownerTeamDamageList[id] == nil then
                        ownerTeamDamageList[id] = {id = id, value = UnitStat.getTotalDamage(unitStat), name = entityModel:getName(),kind = "meleeAttack"}
                    else
                        ownerTeamDamageList[id].value = UnitStat.getTotalDamage(unitStat)
                    end
                end
            else
                if isInMyTeam and entityModel:isHero() and not entity:isSummon() and not Unit.isSummonerClone(entity) then
                    --牧师神圣专精 治疗
                    --战士防御专精 仇恨
                    --其他 伤害
                    if self:getSpecialistID() == Enums.SpecialistID.PriestHoly then
                        local unitStat = Unit.getUnitStat(entity)
                        if ownerTeamDamageList[id] == nil then
                            ownerTeamDamageList[id] = {id = id, value = UnitStat.getTotalHeal(unitStat), name = entityModel:getName(),kind = "meleeHeal"}
                        else
                            ownerTeamDamageList[id].value = UnitStat.getTotalHeal(unitStat)
                        end
                    elseif self:getSpecialistID() == Enums.SpecialistID.WarriorDefense then
                        local targetId =  self.targetId
                        if targetId then
                            local targetEntity = battleLoop:getEntityById(targetId)
                            if cc.isAlive(targetEntity) and targetEntity.teamId ~= controlledEntityModel.teamId then
                                if ownerTeamDamageList[id] == nil then
                                    ownerTeamDamageList[id] = {id = id, value = targetEntity:getThreat(id), name = entityModel:getName(),kind = "meleeAngry"}
                                else
                                    ownerTeamDamageList[id].value = targetEntity:getThreat(id)
                                end
                            else
                                ownerTeamDamageList = {}
                            end
                        else
                            ownerTeamDamageList = {}
                        end
                    else
                        local unitStat = Unit.getUnitStat(entity)
                        if ownerTeamDamageList[id] == nil then
                            ownerTeamDamageList[id] = {id = id, value = UnitStat.getTotalDamage(unitStat), name = entityModel:getName(),kind = "meleeAttack"}
                        else
                            ownerTeamDamageList[id].value = UnitStat.getTotalDamage(unitStat)
                        end
                    end
                end
            end
            local isSelf = id == controlledEntityId

            if isSelf then
                local money = entity:getMoney()
                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_PROP,
                    money,
                    entity:getBuyedItemsByType(Enums.ShopItemType.Buff),
                    entity:getBuyedItemsByType(Enums.ShopItemType.Skill),
                    entity:getSoul(),
                    entity)
                if Unit.dead(entity) then
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_DEADCD,entity:getReviveTime(),entity:getReviveIntervalTime(),id)
                else
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_DEADCD,0,entity:getReviveIntervalTime(),id)
                end

                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_UPDATE_MONEY,money)
            end
        end
    end

    --刷新竞技场相关
    self:updatePvpUI(logicEntities)

    --刷新伤害排行
    if not battleModel:isKofBattle() then
        self:updateDamages(ownerTeamDamageList,controlledEntityId)
    else
        self:updateDamages({},controlledEntityId)
    end

    if battleModel:isMeleeBattle() or battleModel:isZombieBattle() then
        --刷新小地图
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_MAP, self.views ,LocationConfig, battleModel:getBattleType())
    end
end

function BattleController:getSkillTargets(showTargetSkill)
    local rangeKind = Skill_getSkillDamageRangeKind(showTargetSkill)

    -- local view
    local targetsIdList

    if rangeKind == Enums.DamageRangeKind.DR_Kind_Single then
        local targetId = Skill_targetId(showTargetSkill)
        -- view = self.views[targetId]
        targetsIdList = {targetId}
    elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Region then
        targetsIdList = Skill_getPredictTargetsId(showTargetSkill)
    elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Caster_Region then
        targetsIdList = Skill_getPredictTargetsId(showTargetSkill)
    elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Screen then
        targetsIdList = Skill_getPredictTargetsId(showTargetSkill)
    end

    return targetsIdList
end

function BattleController:showTargetWarnning(skills, isWarnedForController)
    local id
    local leftChantTime

    --找出吟唱剩余时间最短的技能
    local showTargetSkill = nil
    local shortTime = nil
    for _,skill in pairs(skills) do
        leftChantTime = Skill_getLeftChantTime(skill)
        if not shortTime then
            shortTime = leftChantTime
            showTargetSkill = skill
        else
            if leftChantTime < shortTime then
                shortTime = leftChantTime
                showTargetSkill = skill
            end
        end
    end

    --显示目标警告
    if showTargetSkill and shortTime then
        local targetWarnnings = {}
        local tempTime
        local view

        local timeNum = math.floor(shortTime/1000)

        local rangeKind = Skill_getSkillDamageRangeKind(showTargetSkill)
        local targetId = Skill_targetId(showTargetSkill)
        local targetsList

        -- if showTargetSkill:id() == 48201041 then
        --     print("=============showTargetWarnning skill 48201041 rangeKind:", rangeKind,targetKind)
        -- end

        if rangeKind == Enums.DamageRangeKind.DR_Kind_Single then
            local hasProjectile = skillInterface.hasProjectile(showTargetSkill)

            local targetKind = Skill_getTargetKind(showTargetSkill)

            local range
            local rangeDisplay
            local posX

            local projectileRangeKind
            if hasProjectile then
                --如果是弹道
                projectileRangeKind = skillInterface.getProjectileDamageRangeKind(showTargetSkill)
                if projectileRangeKind == Enums.DamageRangeKind.DR_Kind_Region or projectileRangeKind == Enums.DamageRangeKind.DR_Kind_Screen or projectileRangeKind == Enums.DamageRangeKind.DR_Kind_Caster_Region then
                    range = skillInterface.getProjectileDamageRange(showTargetSkill)
                    rangeDisplay = LocationConfig:getWidthOnEntityLayer(range*2)
                end
            end
            if targetKind == Enums.TargetKind.Point or targetKind == Enums.TargetKind.FollowParty_Point then
                --如果是点目标

                local pos = Skill_getReleaseTargetPoint(showTargetSkill)
                -- if showTargetSkill:id() == 48201041 then
                --     print("=============showTargetWarnning skill 48201041 pos:", pos)
                -- end
                posX = LocationConfig:getPosOnEntityLayer(pos)

                if hasProjectile then
                    --如果是弹道
                    if rangeDisplay then
                        -- view:setWarningRange(true, projectileRangeKind, rangeDisplay)
                        self:showPointWarning(true, posX, rangeDisplay)
                        --todo 获取伤害范围里的units
                        targetsList = skillInterface.getPredictTargetsProjectile(showTargetSkill)
                    end
                else
                    range = Skill_getDamageRange(showTargetSkill)
                    -- print("========DR_Kind_Region======range:",range)
                    rangeDisplay = LocationConfig:getWidthOnEntityLayer(range*2)

                    self:showPointWarning(true, posX, rangeDisplay)

                    --获取伤害范围里的units
                    targetsList = Skill_getPredictTargets(showTargetSkill)
                end
            else
                --如果是角色目标
                view = self.views[targetId]
                if view then
                    posX = view:getPositionX()
                    if hasProjectile then
                        if rangeDisplay then
                            view:setWarningRange(true, projectileRangeKind, rangeDisplay)
                        end
                        --todo 获取伤害范围里的units
                        targetsList = skillInterface.getPredictTargetsProjectile(showTargetSkill)
                    else
                        if self.dbmMgr and UD.setting:isShowDBM() then
                            self.dbmMgr:onSkillSingMarkTarget(targetId, showTargetSkill)
                        end

                        view:setWarning(true, isWarnedForController, timeNum, rangeKind, true)
                    end
                end
            end

            --伤害范围里的人 警告标记
            -- if rangeDisplay ~= nil and posX ~= nil then
            --     local halfRange = rangeDisplay/2.0
            --     for k,view in pairs(self.views) do
            --         if view and (not view:isDead()) then
            --             local viewPosX = view:getPositionX()
            --             if math.abs(viewPosX - posX) < halfRange then
            --                 view:setWarning(true, isWarnedForController, timeNum, rangeKind, false, rangeDisplay)
            --             end
            --         end
            --     end
            -- end

            if targetsList and rangeDisplay then
                for k,v in pairs(targetsList) do
                    id = Entity.getId(v)
                    view = self.views[id]
                    if view then
                        local isMainTarget = id == targetId
                        view:setWarning(true, isWarnedForController, timeNum, rangeKind, isMainTarget, rangeDisplay)

                        if self.dbmMgr and UD.setting:isShowDBM() then
                            self.dbmMgr:onSkillSingMarkTarget(id, showTargetSkill)
                        end

                        if targetKind == Enums.TargetKind.FollowParty and isMainTarget then
                            if hasProjectile then
                                view:setWarningRange(true, projectileRangeKind, rangeDisplay)
                            else
                                view:setWarningRange(true, rangeKind, rangeDisplay)
                            end
                        end
                        --self.mBattleUIView:setWarning(id,true, timeNum)
                    end
                end
            end
        elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Region then
            local range = Skill_getDamageRange(showTargetSkill)
            -- print("========DR_Kind_Region======range:",range)
            local rangeDisplay = LocationConfig:getWidthOnEntityLayer(range*2)
            --是否是在目标的范围
            local targetKind = Skill_getTargetKind(showTargetSkill)
            if targetKind == Enums.TargetKind.None then
                --如果是无目标，则以释放者为参考范围
                local caster = Skill_unit(showTargetSkill)
                if caster then
                    local casterId = Entity.getId(caster)
                    local casterView = self.views[casterId]
                    if casterView then
                        casterView:setWarningRange(true, rangeKind, rangeDisplay)
                    end
                end
            elseif targetKind == Enums.TargetKind.Point or targetKind == Enums.TargetKind.FollowParty_Point then

                --没有实体目标，只有点目标 todo
                local pos = Skill_getReleaseTargetPoint(showTargetSkill)
                local posX = LocationConfig:getPosOnEntityLayer(pos)
                self:showPointWarning(true, posX, rangeDisplay)

                -- local caster = Skill_unit(showTargetSkill)
                -- if caster then
                --     local casterId = Entity.getId(caster)
                --     local casterView = self.views[casterId]
                --     if casterView then
                --         casterView:setWarningRange(true, rangeKind, rangeDisplay)
                --     end
                -- end
            end

            targetsList = Skill_getPredictTargets(showTargetSkill)
            for k,v in pairs(targetsList) do
                id = Entity.getId(v)
                view = self.views[id]
                if view then
                    local isMainTarget = id == targetId
                    view:setWarning(true, isWarnedForController, timeNum, rangeKind, isMainTarget, rangeDisplay)

                    if self.dbmMgr and UD.setting:isShowDBM() then
                        self.dbmMgr:onSkillSingMarkTarget(id, showTargetSkill)
                    end

                    if targetKind == Enums.TargetKind.FollowParty and isMainTarget then
                        view:setWarningRange(true, rangeKind, rangeDisplay)
                    end
                    --self.mBattleUIView:setWarning(id,true, timeNum)
                end
            end
        elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Caster_Region then
            local range = Skill_getDamageRange(showTargetSkill)
            local rangeDisplay = LocationConfig:getWidthOnEntityLayer(range)

            local caster = Skill_unit(showTargetSkill)
            if caster then
                local casterId = Entity.getId(caster)
                local casterView = self.views[casterId]
                if casterView then
                    casterView:setWarningRange(true, rangeKind, rangeDisplay)
                end
            end

            targetsList = Skill_getPredictTargets(showTargetSkill)
            for k,v in pairs(targetsList) do
                id = Entity.getId(v)
                view = self.views[id]
                if view then
                    local isMainTarget = id == targetId
                    view:setWarning(true, isWarnedForController, timeNum, rangeKind, isMainTarget, rangeDisplay)

                    if self.dbmMgr and UD.setting:isShowDBM() then
                        self.dbmMgr:onSkillSingMarkTarget(id, showTargetSkill)
                    end

                    --self.mBattleUIView:setWarning(id,true, timeNum)
                end
            end
        elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Screen then
            targetsList = Skill_getPredictTargets(showTargetSkill)
            for k,v in pairs(targetsList) do
                id = Entity.getId(v)
                view = self.views[id]
                if view then
                    local isMainTarget = id == targetId
                    view:setWarning(true, isWarnedForController, timeNum, rangeKind, isMainTarget)
                    --self.mBattleUIView:setWarning(id,true, timeNum)
                end
            end

            --全屏效果显示
            self:showScreenWarning(true, timeNum)
        end
    end
end


function BattleController:isTargetInSkillRange(skill, unitId)
    local showTargetSkill = skill
    if showTargetSkill then
        local targetWarnnings = {}
        local view

        local rangeKind = Skill_getSkillDamageRangeKind(showTargetSkill)
        local targetId = Skill_targetId(showTargetSkill)
        local targetsList


        if rangeKind == Enums.DamageRangeKind.DR_Kind_Single then
            local hasProjectile = skillInterface.hasProjectile(showTargetSkill)

            local targetKind = Skill_getTargetKind(showTargetSkill)

            local range
            local rangeDisplay
            local posX

            local projectileRangeKind
            if hasProjectile then
                --如果是弹道
                projectileRangeKind = skillInterface.getProjectileDamageRangeKind(showTargetSkill)
                if projectileRangeKind == Enums.DamageRangeKind.DR_Kind_Region or projectileRangeKind == Enums.DamageRangeKind.DR_Kind_Screen or projectileRangeKind == Enums.DamageRangeKind.DR_Kind_Caster_Region then
                    range = skillInterface.getProjectileDamageRange(showTargetSkill)
                    rangeDisplay = LocationConfig:getWidthOnEntityLayer(range*2)
                end
            end
            if targetKind == Enums.TargetKind.Point or targetKind == Enums.TargetKind.FollowParty_Point then
                --如果是点目标

                local pos = Skill_getReleaseTargetPoint(showTargetSkill)

                posX = LocationConfig:getPosOnEntityLayer(pos)

                if hasProjectile then
                    --如果是弹道
                    if rangeDisplay then
                        --todo 获取伤害范围里的units
                        targetsList = skillInterface.getPredictTargetsProjectile(showTargetSkill)
                    end
                else
                    --获取伤害范围里的units
                    targetsList = Skill_getPredictTargets(showTargetSkill)
                end
            else
                --如果是角色目标
                view = self.views[targetId]
                if view then
                    posX = view:getPositionX()
                    if hasProjectile then
                        --todo 获取伤害范围里的units
                        targetsList = skillInterface.getPredictTargetsProjectile(showTargetSkill)
                    end
                end
            end
        elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Region then
            targetsList = Skill_getPredictTargets(showTargetSkill)
        elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Caster_Region then
            targetsList = Skill_getPredictTargets(showTargetSkill)
        elseif rangeKind == Enums.DamageRangeKind.DR_Kind_Screen then
            targetsList = Skill_getPredictTargets(showTargetSkill)
        end

        if targetsList then
            for k,v in pairs(targetsList) do
                local id = Entity.getId(v)
                if id == unitId then
                    return true
                end
            end
        end
    end
    return false
end

function BattleController:getControlledUnitClassId()
    local entity = self.model:getControlledEntity()
    if entity then
        return entity:getClassId()
    end
    return -1
end

function BattleController:getSpecialistID()
    local entity = self.model:getControlledEntity()
    if entity then
        return entity:getSpecialistID()
    end
    return -1
end

function BattleController:setCameraOffset(offsetX)
    if self.model:isMeleeBattle() then -- 大乱斗不设镜头偏移
        return
    end

    MapManager:getMap():setMapAdjudtX(offsetX)
end

function BattleController:getCameraOffset()
    return MapManager:getMap():getMapAdjustX()
end

function BattleController:calcCameraMove(dt)
    local classID = self:getControlledUnitClassId()
    if classID == Enums.Profession.mage
      or classID == Enums.Profession.preist
      or classID == Enums.Profession.hunter then
        local controlledEntityId = self.model:getControlledEntityId()
        local currentPlayerTargetId = self.targetId
        local targetView = self.views[currentPlayerTargetId]
        local selfView = self.views[controlledEntityId]
        if cc.isAlive(targetView) and cc.isAlive(selfView) then
            if self:isAlreadAttack() then
                local offsetX = (targetView:getPositionX() - selfView:getPositionX())/2
                self:setCameraOffset(offsetX)
                self.cameraMoveDelay = 0
            end
        else
            self.cameraMoveDelay = self.cameraMoveDelay + dt
            if self.cameraMoveDelay >= Constant.BattleCameraMoveDelay then
                self:setCameraOffset(0)
                self:setAlreadAttack(false)
            end
        end
    end
end

function BattleController:showScreenWarning(isVisible, timeNum)
    --self.mBattleUIView:showScreenWarning(isVisible, timeNum)
    local y = self.altitude or 100
    self.entityFrontLayer:showScreenWarning(isVisible, y, self.screenScale)
end

--显示点目标警告
function BattleController:showPointWarning(isVisible, posX, rangeDisplay)
    local y = self.altitude or 100
    self.entityFrontLayer:showPointWarning(isVisible, y, posX, rangeDisplay)
end

-- function BattleController:spawnSkillEffect(event)
--     if self.visualEffect then
--         local casterId = event.casterId
--         local casterView = self.views[casterId]
--         self.visualEffect:spawnSkillEffect(event,casterView)
--     end
-- end

function BattleController:charAndSkillUI(currentRealTime)
    local controlledEntityId = self.model:getControlledEntityId()
    local currentGameTime = self.model:getBattleLogicTime()
    local alive = self.model:alive()
    local skills = self:mySkills()
    local unit = self.model.mBattleLoop:getEntityById(controlledEntityId)
    local restrictedEffects = Unit.getAllRestrictedSkillBuffEffects(unit)
    local subscribeSkillId = unit:getSubscribeSkillId()
    local data = {alive, restrictedEffects, self.model, skills, currentGameTime, self.property,
                  subscribeSkillId, self.showCanBreak}
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_UPDATE,unpack(data))
end

--发送技能选择
function BattleController:sendInput(event)
    --todo
end

function BattleController:setAllUIVisible(event)
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.UI_SHOW,event.isVisible)
end

function BattleController:showAllUI()
    self:displayAllUI(true)
end

function BattleController:displayAllUI(b)
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.UI_SHOW,b)
    self.uiLayer:setVisible(b)
end

function BattleController:forceDisplayUI(uiName,b)
    self.forceUIVisible[uiName] = b
    local uiView = self[uiName]
    if uiView then
        uiView:setVisible(b)
    end
end

function BattleController:forceGameOver()
    self:onGameOver({})
end

function BattleController:randomMusic(isBossBattle)
    local battleMusicList = {}
    if isBossBattle then
        battleMusicList = GD:queryBattleBossMusics()
    else
        battleMusicList = GD:queryBattleNormalMusics()
    end
    local count = #battleMusicList
    if count > 0 then
        local index = math.random(1,count)
        local battleMusic = battleMusicList[index]
        if battleMusic and battleMusic.path then
            return battleMusic.path
        end
    end
end

function BattleController:playMusic(path)
    if path then
        self.musicId = AM.play(path,true,AM.TagMusic)
        -- AM.fadeIn(self.musicId,1)
    end
end

function BattleController:stopMusic()
    if self.musicId then
        AM.fadeOut(self.musicId,1)
        --AM.stop(self.musicId)
        self.musicId=nil
    end
end

function BattleController:exitMusic()
    if self.musicId then
        -- AM.fadeOut(self.musicId,1)
        AM.stop(self.musicId)
        self.musicId=nil
    end
end

function BattleController:onEnter()
    -- self:playMusic()

    --cc.EnableLeakMonitor(true)

    tapm.markLevelLoadCompleted()

    --debug.profiStart(1)
    self.model:init()
end

function BattleController:onExit()
    self:removeAllEventListeners()

    tapm.markLevelFin()

    local scheduler = cc.Director:getInstance():getScheduler()
    scheduler:setTimeScale(1)

    --不使用fade，以防断线重连是crash
    self:exitMusic()

    if self.uiLayer then
        self.uiLayer:removeFromParent()
        self.uiLayer = nil
    end

    if self.uiFloatLayer then
        self.uiFloatLayer:removeFromParent()
        self.uiFloatLayer = nil
    end

    --移除掉战斗中未显示的提示
    display.clearToastByTag(Enums.ToastTag.battle)

    self.model = nil
    self.visualEffect = nil


    if self.dbmMgr then
        self.dbmMgr:clear()
        self.dbmMgr = nil
    end

    --debug.profiStop()
end

function BattleController:onCleanup()
    --战斗结束后释放缓存,为了战斗体验暂时先不释放. by will
    --EM:notify("OnGameSceneExit")
    --display.purgeUnUsedArmatureCachedData()
    --cc.Director:getInstance():getTextureCache():removeUnusedTextures()
    --cc.SpriteFrameCache:getInstance():removeUnusedSpriteFrames()

    --[[
    scheduler.performWithDelayGlobal(function()
        cc.EnableLeakMonitor(false)
        cc.PrintLeaks()
    end,2)
    ]]
end

--客户端战斗结束后开始计时 时间到了还未收到服务器战斗结束消息的话自己结束 防止卡画面
function BattleController:onClientBattleOver()
    --倒计时一定时间后执行
    BattleManager:clearClientWeakEndCB()

    --根据战斗类型来区分是否有mvp 如果有 时间需要更长
    local delayTime = 5
    if self.model:isPvpBattle() or self.model:isMeleeBattle() then
        delayTime = 10
    end

    local cronIdx = scheduler.newCron(function()
        --播放的时候将数据插入
        app:dispatchEvent({name="EVENT_BATTLE_END",isClientBattleEnd = true})
    end, delayTime)

    BattleManager:setClientWeakEndCBId(cronIdx)
end


function BattleController:tick_(dt)
    if not self.flagReady then
        return
    end
    BattleUIEvent:updateFrame(dt)

    self.entityWarnningLayer:setScale(self.screenScale)
    self.entityBubbleLayer:setScale(self.screenScale)
    self.sceneMaskLayer:setScale(self.screenScale)
    self.entityStatebarLayer:setScale(self.screenScale)
    self.sceneMaskLayer:setPosition(self.sceneMaskLayer:getParent():toLocalPosition(0,0))
    self.mvpShowLayer:setScale(self.screenScale)
    self.mvpShowLayer:setPosition(self.sceneMaskLayer:getParent():toLocalPosition(0,0))

    if self.isGameOver then
        self.model:tick_(dt)
        return
    end

    if BATTLE_PREPARE_LOAD and not self:isStartState() then
        if self:isPrepareState() then
            self:prepareLoadBattleResOneFrame()
            if self:checkPrepareLoadEnd() then
                self._state = Enums.BattleState.removeUnusedRes
            end
            return
        end
        if self:isRemoveUnusedResState() then
            self:removeUnusedRes()
            self:start()
            return
        end
    end

    if self.entityCreateSequence then
        if #self.entityCreateSequence == 0 then
            for _,view in pairs(self.views) do
                view:setVisible(true)
            end
            self:onAllEntityCreated()
            self.entityCreateSequence=nil
        else
            local entity = self.entityCreateSequence[1]
            local view = self:createViewByEntityModel(entity)
            table.remove(self.entityCreateSequence,1)
            view:setVisible(false)
            local playerNode = view:getPlayerNode()
            if playerNode then
                playerNode:retain()
            end
        end
        return
    end

    self.model:tick_(dt)

    if cc.isDead( self ) then
        return
    end
    local controlledEntity = self.model:getControlledEntity()
    for id,view in pairs(self.views) do
        local entityModel = self:getEntityModelById(view:getUnitModelId())
        if view and view:isVisible() then
            if self.targetId == id then
                --如果有目标
                view:setLocalZOrder(controlledEntity:getDefaultZOrder() - 1)
            else
                view:setLocalZOrder(entityModel:getDefaultZOrder())
            end
            self.entityFrontLayer:setFloatEffectPlayerLocalZOrder(id, entityModel:getDefaultZOrder())
        end
        if view then
            view:tick(dt)
        end
    end

    if self._skillUIDirty then
        -- print("=====self._skillUIDirty charAndSkillUI=====")
        self:charAndSkillUI(self._currentRealTime)
        self._skillUIDirty = false
    end

    --camera move
    self:calcCameraMove(dt)
end

function BattleController:scheduleOnce(action,delay)
    local scheduler = display.newNode()
    self:addChild(scheduler)
    local delayTime = delay or 0
    local actions = {}
    if delay then
        table.insert(actions,cc.DelayTime:create(delay))
    end
    table.insert(actions,action)
    table.insert(actions,cc.RemoveSelf:create())
    local newAction = cc.Sequence:create(actions)
    scheduler:runAction(newAction)
end

function BattleController:getParentScale()
    if not self.parentScale then
        local parentScale = 1.0
        local parent = self.entityLayer:getParent()
        while parent
        do
            parentScale = parent:getScale() * parentScale

            parent = parent:getParent()
        end
        self.parentScale = parentScale
    end
    return self.parentScale
end

function BattleController:initScaleParam()
    local parentScale = self:getParentScale()

    print("---------------parentScale:"..parentScale)

    self.screenScale = 1.0/parentScale
    self.startPixel = -(display.width * self.screenScale - display.width) / 2.0
end

function BattleController:getScreenScale()
    return self.screenScale
end

function BattleController:getStarPixel()
    return self.startPixel
end

function BattleController:getPrepareResLoadList()
    local listArmaturesSke = {}
    local listSfx = {}

    local function pushCacheTable(skeleton, texture, effectCfg, priority)
        if not listArmaturesSke[skeleton] then
            listArmaturesSke[skeleton] = {textures = {}, effectCfgs = {} , count = 0}
        end
        local priority = priority or 1
        listArmaturesSke[skeleton].count = listArmaturesSke[skeleton].count + priority
        listArmaturesSke[skeleton].textures[texture] = 1
        if BATTLE_PREPARE_CACHE_EFFECT then
            if effectCfg then
                --同一个effectcfg创建多份effect node 缓存
                table.insert(listArmaturesSke[skeleton].effectCfgs, effectCfg)
                --同一个effectcfg创建一份effect node 缓存
                -- local effectId = EffectConfig_getId(effectCfg)
                -- listArmaturesSke[skeleton].effectCfgs[effectId] = effectCfg
            end
        end
    end

    local function cacheArmatureByPath(path, effectCfg, priority)
        if path then
            local skeleton = path.."/skeleton"
            local texture = path.."/texture"
            pushCacheTable(skeleton, texture, effectCfg, priority)
        end
    end

    local function checkObjectCfg(objectCfg, effectCfg, priority)
        if objectCfg then
            local dir = objectCfg:getDir()
            if string.len(dir) > 0 then
                local path = "armatures/"..dir
                cacheArmatureByPath(path, effectCfg, priority)
            end
        end
    end

    local function checkEffectCfg(effectCfg, entityModel, priority)
        if effectCfg then
            local objectCfg = effectCfg:getObjectCfg()
            checkObjectCfg(objectCfg, effectCfg, priority)

            local sfxFile = effectCfg:getSfxFile()
            if string.len(sfxFile) > 0 and entityModel then
                local sfxPath = entityModel:getSfxFilePath(sfxFile)
                if sfxPath then
                    listSfx[sfxPath] = 1
                end
            end
        end
    end

    local battleModel = self.model
    local battleLoop = battleModel.mBattleLoop
    local allEntities = battleModel.entities
    table.walk(allEntities, function(entityModel, k)
        -- 角色外观资源
        if entityModel:isNpc() then
            local skeleton, texture = entityModel:getNPCAvatarParams()
            pushCacheTable(skeleton, texture, nil, 99999) --提高优先级
        elseif entityModel:isHero() then
            -- TODO: Player resource preload list.
        end

        -- 技能资源
        if entityModel:isOriginalEntity() then
            local id = entityModel:getId()
            local unit = battleLoop:getEntityById(id)
            local skills = Unit.getSkills(unit)
            local skillCfg
            local function checkSkillCfg(skillCfg, entityModel)
                --技能特效
                local effectCfgs = SkillConfig_getEffects(skillCfg)
                for k1,effectCfg in pairs(effectCfgs) do
                    checkEffectCfg(effectCfg, entityModel)
                end

                --弹道
                local projectileCfgs = SkillConfig_getProjectiles(skillCfg)
                local objectCfg
                for k2,projectileCfg in pairs(projectileCfgs) do
                    objectCfg = battleModel:getObjectConfig(ProjectileConfig_getObjectId(projectileCfg))
                    checkObjectCfg(objectCfg)

                    --弹道特效
                    local proEffectCfgs = ProjectileConfig_getEffects(projectileCfg)
                    for k3,proEffectCfg in pairs(proEffectCfgs) do
                        checkEffectCfg(proEffectCfg, entityModel)
                    end
                end
            end

            for _,skill in pairs(skills) do
                skillCfg = Skill_cfg(skill)
                checkSkillCfg(skillCfg, entityModel)
                --子技能
                if BATTLE_PREPARE_LOAD_SUB_SKILL then
                    local subSkillIds = SkillConfig_getChannel(skillCfg)
                    local noRepeateSubSkillIds = {} -- 需要去除重复的
                    for k,subSkillId in pairs(subSkillIds) do
                        noRepeateSubSkillIds[subSkillId] = 1
                    end
                    for subSkillId,_ in pairs(noRepeateSubSkillIds) do
                        checkSkillCfg(battleLoop:getSkillConfig(subSkillId), entityModel)
                    end
                end
            end
        end
    end)

    --通用释放技能特效
    -- local SkillHintEffect = battleLoop:getEffectConfig(Res.SkillHintEffectId)
    -- if SkillHintEffect then
    --     checkEffectCfg(SkillHintEffect, nil, 99) --todo sfx not cache
    -- end

    --准备释放技能特效
    cacheArmatureByPath(Res.ReadyReleaseEffect.dir, nil)

    --死亡特效
    cacheArmatureByPath(Res.DeadEffect.dir, nil)

    --选中特效
    cacheArmatureByPath(Res.ActorSelectEffect.dir, nil)

--    for k,v in pairs(listArmaturesSke) do
--        print("==>PrepareResLoadList armatures ske:",k)
--    end

--    for k,v in pairs(listSfx) do
--        print("==>PrepareResLoadList sfx :",k)
--    end

    return listArmaturesSke, listSfx
end

function BattleController:prepareLoadBattleResOneFrame()
    local count = self.prepareLoadResCountPerFrame
    local fileUtils = cc.FileUtils:getInstance()
    local dbFactory = db.CCFactory:getInstance()
    local resCount = #(self.listSort)
    for idx = resCount, 1, -1 do
        local skeFile = self.listSort[idx].ske
        -- print("-----prepareLoadBattleResOneFrame skeFile: ",skeFile)
        local content = self.listArmaturesSke[skeFile]
        --加载骨骼资源
        local skeletonPath = skeFile..".dbb"
        if not fileUtils:isFileExist(skeletonPath) then
            skeletonPath = skeFile..".xml"
        end
        local skeletonKey = fileUtils:fullPathForFilename(skeletonPath)
        dbFactory:loadDragonBonesData(skeletonPath,skeletonKey)
        --加载贴图资源
        local listArmaturesTex = content.textures
        for texFile,_ in pairs(listArmaturesTex) do
            -- print("-----prepareLoadBattleResOneFrame texFile: ",texFile)
            local texturePath = texFile..".dbb"
            if not fileUtils:isFileExist(texturePath) then
                texturePath = texFile..".xml"
            end
            local textureKey = fileUtils:fullPathForFilename(texturePath)
            dbFactory:loadTextureAtlasData(texturePath,textureKey)
        end
        --缓存effect node
        if BATTLE_PREPARE_CACHE_EFFECT then
            local listEffectCfg = content.effectCfgs
            for _,effectCfg in pairs(listEffectCfg) do
                self.visualEffect:cacheEffectByCfg(effectCfg)
            end
        end

        --清除加载过的
        table.remove(self.listSort, idx)
        self.listArmaturesSke[skeFile] = nil

        count = count - 1
        if count <= 0 then
            break
        end
    end

    --TODO:音效预加载
--    for k,sfx in pairs(self.listSfx) do
--
--    end
end

function BattleController:checkPrepareLoadEnd()
    if BATTLE_PREPARE_LOAD_TIME_LIMIT then
        local currentTime = app:getUTCTime()
        local loadTimeLimit = 2 --限制加载两秒，超时后不加载
        if currentTime - self.startPrepareLoadTime >= loadTimeLimit then
            -- dump(self.listArmaturesSke, "not load res", 6)
            if BATTLE_PREPARE_LOAD_ASYNC_LEFT_RES then
                local fileUtils = cc.FileUtils:getInstance()
                local resLoadManager = db.ResLoadManager:getInstance()
                local function callback(isSuccess)
                    print("======BATTLE_PREPARE_LOAD_TIME_LIMIT Async ",isSuccess)
                end
                local listSort = self.listSort
                for idx = #listSort, 1, -1 do
                    local skeFile = listSort[idx].ske
                    local content = self.listArmaturesSke[skeFile]
                    -- dump(content,"content",6)
                    --加载骨骼资源
                    local skeletonPath = skeFile..".dbb"
                    if not fileUtils:isFileExist(skeletonPath) then
                        skeletonPath = skeFile..".xml"
                    end
                    local skeletonKey = fileUtils:fullPathForFilename(skeletonPath)

                    --加载贴图资源
                    local listArmaturesTex = content.textures
                    for texFile,_ in pairs(listArmaturesTex) do
                        local texturePath = texFile..".dbb"
                        if not fileUtils:isFileExist(texturePath) then
                            texturePath = texFile..".xml"
                        end
                        local textureKey = fileUtils:fullPathForFilename(texturePath)
                        resLoadManager:addDragonBonesAsync(skeletonKey, skeletonKey, textureKey, textureKey, callback)
                    end
                end
            end
            return true
        end
    end

    local isEnd = true
    if self.listArmaturesSke and table.nums(self.listArmaturesSke) > 0 then
        isEnd = false
    end

    -- if self.listArmaturesTex and table.nums(self.listArmaturesTex) > 0 then
    --     isEnd = false
    -- end

    --TODO:音效预加载
--    if self.listSfx and table.nums(self.listSfx) > 0 then
--        isEnd = false
--    end

    return isEnd
end

function BattleController:isInitState()
    return self._state == Enums.BattleState.init
end

function BattleController:isPrepareState()
    return self._state == Enums.BattleState.prepare
end

function BattleController:isRemoveUnusedResState()
    return self._state == Enums.BattleState.removeUnusedRes
end

function BattleController:isStartState()
    return self._state == Enums.BattleState.start
end

function BattleController:isEnterState()
    return self._state == Enums.BattleState.enter
end

function BattleController:ready(event)
    self.locationCount = event.locationCount

    if BATTLE_PREPARE_LOAD then
        self:prepare()
    else
        self:start()
    end
    self.flagReady = true
--    self:scheduleUpdate(handler(self, BattleController.tick_))
end

function BattleController:prepare()
    self._state = Enums.BattleState.prepare
    self.startPrepareLoadTime = app:getUTCTime()

    self.listArmaturesSke, self.listSfx = self:getPrepareResLoadList()
    self.listSort = {}
    for k,v in pairs(self.listArmaturesSke) do
        table.insert(self.listSort, {ske = k, count = v.count})
    end
    local function sortSke(a,b)
        return a.count < b.count
    end
    table.sort(self.listSort, sortSke)
--    local loadResCount = table.nums(self.listArmaturesSke)
--    print("=====loadResCount:",loadResCount)
--    local loadResFrameCount =  math.ceil(loadResCount/BATTLE_PREPARE_LOAD_COUNT_PER_FRAME)
--    print("=====loadResFrameCount:",loadResFrameCount)
end

function BattleController:removeUnusedRes()
    display.purgeUnUsedArmatureCachedData()
end

function BattleController:start()
    self._state = Enums.BattleState.start
    self.isBossBattle = false
    self.entityCreateSequence = {}

    if self.visualEffect then
        self.visualEffect:init({battleController = self,})
        self.visualEffect:start()
    end



    self.defaultScales =
    {
        characterScale = self.scales.characterScale,
        npcScale = self.scales.npcScale,
        bossScale = self.scales.bossScale,
        mecScale = self.scales.mecScale,
    }

    if not UD.setting:isManualChanged() then
        self:setFrog(self.model.mBattleLoop:isOpenDenseFog())
    end

    local locationCount = self.locationCount
    local entityLayer = self.entityLayer
    local battleModel = self.model
    local controlledEntityId = battleModel:getControlledEntityId()
    local controlledEntity = battleModel:getControlledEntity()
    local allEntities = battleModel.entities

    --初始化dbm數據
    self.dbmMgr:start(self,battleModel:getBattleId(), battleModel:getControlledEntityId())

    local bossEntityIds = {}
    table.walk(allEntities,function(entityModel,k)
        if entityModel:isOriginalEntity() then
            table.insert(self.entityCreateSequence, entityModel)
        end
        if entityModel:isBoss() then
            self.isBossBattle = true
            bossEntityIds[#bossEntityIds + 1] = entityModel:getId()
        end
    end)

    local battleFieldPos = controlledEntity:getPos()
    local characterEntityLayerPos = entityLayer:toLocalPosition(self.mainCharacterPosX, 0)
    local battleScale = LocationConfig:calculate(locationCount, self.screenScale, characterEntityLayerPos, battleFieldPos,
        battleModel:isPvpBattle() or battleModel:isKofBattle() or battleModel:isMeleeBattle() or battleModel:isDuelBattle())
    self.mainCharacterPosX = characterEntityLayerPos
    self:dispatchEvent("GameInit", battleScale)

    -- TODO: 卡顿
    self:initMainUI()

    self.touchMaskLayer = ccui.Layout:create()
    self.touchMaskLayer:setContentSize(display.width, display.height)
    self.touchMaskLayer:setTouchEnabled(false)
    self.uiLayer:addChild(self.touchMaskLayer)
    self.mTouchMaskListener = cc.EventListenerTouchOneByOne:create()
    self.touchMaskLayer:setSwallowTouches(false)
    self.mTouchMaskListener:registerScriptHandler(
        function(touch, event)
            return true
        end, cc.Handler.EVENT_TOUCH_BEGAN)
    self.mTouchMaskListener:registerScriptHandler(
        function()
            if self.touchMaskLayer:isSwallowTouches() then
                app:popMessage("Touch blocked!", nil, nil, Enums.ToastTag.battle)
            end
        end, cc.Handler.EVENT_TOUCH_ENDED)
    self.touchMaskLayer:getEventDispatcher():addEventListenerWithSceneGraphPriority(self.mTouchMaskListener, self.touchMaskLayer)

    -- 特殊战斗UI初始化
    if battleModel:isPvpBattle() then
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_PVP_INIT_TOP,
            {
                isSelfLeft = true,
                initReviveTimes = self.model:getInitReviveTimes(controlledEntity.teamId),
                maxReviveTimes = self.model:getMaxReviveTimes(controlledEntity.teamId),
            })
    elseif battleModel:isMeleeBattle() or battleModel:isZombieBattle() then
        if battleModel:isZombieBattle() then
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.FISH_LAYOUT)
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_FISH_INIT_TOP,{battleLength = battleModel:getGameLength(), })
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_REFRESH_ROUND, 1, Constant.BattleRefreshFirstRoundTime)
        elseif battleModel:isMeleeBattle() then
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_LAYOUT)
        end
    elseif battleModel:isTheatrePve() then -- 歌剧院pve战斗
        self._bossEntityIds = bossEntityIds

        -- 强制视野到地图中央
        local midPosX = GD:getTheatrePar("PVPPosition", true)
        self:onFocusPos(midPosX, true)
    elseif battleModel:isKofBattle() then
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_SHOW_KOF_UI, {isSelfLeft = true})
        -- 所有角色头像信息 刷新到UI
        local myKofUIData = {}
        local enemyKofUIData = {}
        local enemyUid
        local function pushKofUIData(list)
             table.walk(list,function(entityModel,k)
                if entityModel:isHero() then
					local kofData =
                    {
						icon = entityModel:getFaceSideIcon(),
						name = entityModel:getName()
					} 					                
                    if entityModel:isInMyTeam() then
                        table.insert(myKofUIData, kofData)
                    else
                        --敌方队伍
                        enemyUid = entityModel:getUid()
						kofData.icon = entityModel:getFaceSideEnemyIcon()
                        table.insert(enemyKofUIData, kofData)
                    end
                end
            end)
        end

        --先把上阵的塞进table
        pushKofUIData(self.entityCreateSequence)
        --把后备的kof塞进去
        local kofEntities = battleModel.kofEntities
        if kofEntities then
            pushKofUIData(kofEntities)
        end

        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_KOF_UI_HEAD_INIT,
            {
                myKofUIData = myKofUIData,
                enemyKofUIData = enemyKofUIData,
                myUid = UD.player.uid,
                enemyUid = enemyUid,
                myTeamId = battleModel:getMyTeamId(),
                enemyTeamId = battleModel:getEnemyTeamId(),
            })
    elseif battleModel:isTraining() then
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_SHOW_HIDE_LEFTRIGHT_VIEW, false)
    end
end

local function sortEntitys(l,r)
    local lzorder = l:getDefaultZOrder()
    local rzorder = r:getDefaultZOrder()
    return lzorder > rzorder
end

local function setViewLine(entities, isSelfTeam, controlledEntityId)
    local specialEntityNums = 0 -- 特殊单位，boss/自己 单独占一条线的
    for k, entityModel in pairs(entities) do
        if isSelfTeam then
            if entityModel:getId() == controlledEntityId then
                specialEntityNums = specialEntityNums + 1
                break
            end
        else
            if entityModel:isBoss() then
                specialEntityNums = specialEntityNums + 1
            end
        end
    end

    local count = (#entities) - specialEntityNums
    --每条线上平均数量
    local normalLineNum = 2 --己方普通 3 4线，敌方普通 1 3线
    local lineCount = count/ normalLineNum
    if lineCount < 1 then
        lineCount = 1
    end
    local lineIndex = 1
    local currentIndex
    local currentNum = 0
    -- if isSelfTeam then
    --     lineIndex = 3 -- 己方从3线开始
    --     currentNum = 0
    --     for k,v in pairs(entities) do
    --         if v.id == controlledEntity.id then
    --             --如果是自己，放到2线
    --             currentIndex = 2
    --         else
    --             currentNum = currentNum + 1
    --             -- local lineMax = lineIndex*lineCount
    --             if currentNum > lineCount then
    --                 -- lineIndex = lineIndex + 1
    --                 currentNum = 1
    --                 lineIndex = 4 -- 超过了就放到 4线
    --             end

    --             -- if lineIndex > Constant.BattleLineNum then
    --             --     lineIndex = Constant.BattleLineNum
    --             -- end
    --             currentIndex = lineIndex
    --         end

    --         local view = self.views[v.id]
    --         view:setLine(currentIndex)
    --         local y = view:getPosYByLine()
    --         view:setPositionY(y)
    --     end
    -- else
    --     lineIndex = 1 -- 敌方从1线开始
    --     currentNum = 0
    --     for k,v in pairs(entities) do
    --         if v:isBoss() then
    --             --如果是boss，放到4线
    --             currentIndex = 4
    --         else
    --             currentNum = currentNum + 1
    --             -- local lineMax = lineIndex*lineCount
    --             if currentNum > lineCount then
    --                 -- lineIndex = lineIndex + 1
    --                 currentNum = 1
    --                 lineIndex = 3 -- 超过了就放到 3线
    --             end

    --             -- if lineIndex > Constant.BattleLineNum then
    --             --     lineIndex = Constant.BattleLineNum
    --             -- end
    --             currentIndex = lineIndex
    --         end

    --         local view = self.views[v.id]
    --         view:setLine(currentIndex)
    --         local y = view:getPosYByLine()
    --         view:setPositionY(y)
    --     end
    -- end

    --放到一条线上
    -- for k,v in pairs(entities) do
    --     local view = self.views[v.id]
    --     view:setLine(1)
    --     local y = view:getPosYByLine()
    --     view:setPositionY(y)
    -- end
end

--左右头像排列
local function sortLeftPlayerNode(a,b)
    if a.pos and b.pos then
        return b.pos < a.pos
    end
    return true
end

local function sortRightPlayerNode(a,b)
    if a.pos and b.pos then
        return a.pos < b.pos
    end
    return true
end

--所有角色创建完毕
function BattleController:onAllEntityCreated()
    local battleModel = self.model
    local allEntities = battleModel.entities
    local controlledEntity = battleModel:getControlledEntity()
    local isLeftSelfTeam = controlledEntity:isLeft()

    local leftPlayerNodeList = {}
    local rightPlayerNodeList = {}
    local leftEntitys = {}
    local rightEntitys = {}

    local ownerPlayerCount = 0
	local lvPos = 0
    table.walk(allEntities,function(entityModel,k)
        if entityModel:isOriginalEntity() then
            local view = self:getEntityView(k)
            local playerNode = view:getPlayerNode()
            if playerNode then
                playerNode.pos = entityModel:getPos()
                table.insert(not view:isEnemy() and leftPlayerNodeList or rightPlayerNodeList, playerNode)
            end
            table.insert(entityModel:isLeft() and leftEntitys or rightEntitys, entityModel)
		
            if entityModel:isHero() and entityModel:isInMyTeam() then
                ownerPlayerCount = ownerPlayerCount + 1
				-- 己方队伍的UID
				local lvUid = entityModel:getUid()
				lvPos = lvPos + 1
				self.myTeamFlower[lvPos] = {heroUid = lvUid, flowerCount = 0}
            end
        end
    end)

    if ownerPlayerCount > 1 then
        self.isSinglePlayerBattle = false
    end

    table.sort(leftEntitys, sortEntitys)
    table.sort(rightEntitys, sortEntitys)

    --左侧
    setViewLine(leftEntitys, isLeftSelfTeam, controlledEntity.id)

    --右侧
    setViewLine(rightEntitys, (not isLeftSelfTeam), controlledEntity.id)

    table.sort(leftPlayerNodeList, sortLeftPlayerNode)
    table.sort(rightPlayerNodeList, sortRightPlayerNode)

    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD, true, leftPlayerNodeList)
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD, false, rightPlayerNodeList)
	
    for _,v in ipairs(leftPlayerNodeList) do
        v:release()
    end

    for _,v in ipairs(rightPlayerNodeList) do
        v:release()
    end

    --debug rect
    if DebugMode then
        --战斗格子
        local count = LocationConfig:getLogicBattleFieldWidth()
        print("=====count :", count)
		--local maxDrawCount = 10

        local pixelUnit = LocationConfig:getSpace()
        print("=====pixelUnit :",pixelUnit)
        local drawOnceCount = 100/pixelUnit
        print("=====drawOnceCount :",drawOnceCount)
        local maxDrawCount = math.ceil(count/drawOnceCount)
        print("=====maxDrawCount :",maxDrawCount)

        for i=1,(maxDrawCount + 1) do
            -- local pos = (count/maxDrawCount)*(i - 1)
            local pos = drawOnceCount*(i-1)
            local x = LocationConfig:getPosOnEntityLayer(pos)
            local y = self.altitude or 100

            local rect = display.newRect(cc.rect(x,y,1,40),{fillColor = cc.c4f(1,0,0,1), borderColor = cc.c4f(0,1,0,1), borderWidth = 1})
            self.entityLayer:addChild(rect)

            local labelX = display.newTTFLabel({
                text = "default",
--                font = "Arial",
                size = 20,
                color = display.COLOR_BLUE,
            })
            labelX:setAnchorPoint(cc.p(0.5,0.5))
            labelX:setPosition(cc.p(x, y + 100))
            labelX:setString(tostring(math.floor(pos)))
            self.entityLayer:addChild(labelX)
        end
    end

    --地图上的栅栏
    local x = LocationConfig:getPosOnEntityLayer(LocationConfig:getLeftPos())
    local leftClampEffect = display.newArmature({path=Res.BattleScreenClampEffect.dir,armatureName=Res.BattleScreenClampEffect.name,animationName="",skeletonName=Res.BattleScreenClampEffect.name})
    self.entityLayer:addChild(leftClampEffect)
    leftClampEffect:setPositionX(x)
    leftClampEffect:getAnimation():gotoAndPlay("idle")

    x = LocationConfig:getPosOnEntityLayer(LocationConfig:getRightPos())
    local rightClampEffect = display.newArmature({path=Res.BattleScreenClampEffect.dir,armatureName=Res.BattleScreenClampEffect.name,animationName="",skeletonName=Res.BattleScreenClampEffect.name})
    self.entityLayer:addChild(rightClampEffect)
    rightClampEffect:setPositionX(x)
    rightClampEffect:getAnimation():gotoAndPlay("idle")

    local leftClampPosX = leftClampEffect:toWorldPosition(0, 0) -- - display.width*(0.1)
    local rightClampPosX = rightClampEffect:toWorldPosition(0, 0) --  + display.width*(0.1)
    if self.model:isMeleeBattle() or self.model:isZombieBattle() then
        leftClampEffect:setVisible(false)
        rightClampEffect:setVisible(false)
    end
    --todo
    if controlledEntity then
        self:initSkillPanel(controlledEntity, controlledEntity.id)
        --print("==========controlledEntity.isLeader:",controlledEntity.isLeader)
        if (controlledEntity:getIsLeader() or self.isSinglePlayerBattle) and self.model.mBattleLoop:canEscape() then
            --如果战斗可以逃跑 并且是队长
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.ESCAPE_SHOWUI)
            --self.mBattleUIView:showEscapeUI()
        end
    end

    self.model:initBuffs()

    self:onActorEnterEnd()

    local playerIcon
    if controlledEntity then
       playerIcon = controlledEntity:getFaceSideIcon()
    end

    self:dispatchEvent("GameBegan",leftClampPosX,rightClampPosX)
    self:playMusic(self.musicPath)

    --显示boss战跳字
--    if self.mNewBattleUIView:isVisible() then
--        local posX,posY = self.mNewBattleUIView:getBossFloatTextPos()
--        if (not posX) or (not posY) then
--            posX = display.width/2.0
--            posY = display.height/2.0
--        end
--        self:showEnterBattleFloatText(posX, posY, self.isBossBattle)
--    end

    local targetString = self.model:getBattleTargetString()
    if targetString and string.len(targetString) > 0 then
        local isNeedShow = true
        if string.find(targetString, "_%%d") then
            local classId = controlledEntity:getClassId()
            targetString = string.format(targetString, classId)
            local limitLevel = tonumber(GD:getSystemPar("battleTipsShow",20))
            if UD:getPlayer().level > limitLevel then
                isNeedShow = false
            end
        end
        if isNeedShow then
            BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_FMTION, L(targetString))
        end
    end

    local isBattleTimeCountDown = self.model:isBattleTimeCountDown()
    --self.mBattleUIView:setIsBattleTimeCountDown(isBattleTimeCountDown)

    local gameLength = self.model:getGameLength()
    --self.mBattleUIView:setGameLength(gameLength)

    self.model:onStartEnd()
    --if not self.isSinglePlayerBattle then
    --BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.QC_SHOW_BTN,true)
    --end
end

function BattleController:createViewInBattle(entityModel)
    local view = self:createViewByEntityModel(entityModel)

    view:setLine(1)

    local playerNode = view:getPlayerNode()
    local isLeft = view:isLeft()
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.PLAYER_ADD,isLeft,{playerNode})

    return view
end

function BattleController:refreshViewLayer(view, isSpecial, isWolfCtrlStatusVisble)
    local targetId = self.targetId
    local inLayerIndex = Enums.BattleActorLayer.back
    if isSpecial then
        inLayerIndex = Enums.BattleActorLayer.special
    elseif view:isSelf() or targetId == view:getId() then
        inLayerIndex = Enums.BattleActorLayer.front
    end

    if isWolfCtrlStatusVisble ~= nil then
        --不为空说明有设置
        --print("=============isWolfCtrlStatusVisble:",isWolfCtrlStatusVisble)
        view:setWolfCtrlStatusVisible(isWolfCtrlStatusVisble)
    end

    if inLayerIndex ~= view:getInLayerIndex() then
        view:retain()
        local parent = view:getParent()
        if parent then
            parent:removeChild(view, false)
        end
        -- view:removeFromParent()
        if inLayerIndex == Enums.BattleActorLayer.special then
            self.entitySpecialLayer:addChild(view)
            view:changeToSpecialLayer()
        elseif inLayerIndex == Enums.BattleActorLayer.front then
            self.entityLayer:addChild(view)
            view:changeToFrontLayer()
        else
            self.entityBackLayer:addChild(view)
            view:changeToBackLayer()
        end
        view:release()
    end
end

function BattleController:createViewByEntityModel(entityModel)
    local battleModel = self.model
    local controlledEntity = battleModel:getControlledEntity()
    local controlledEntityId = battleModel:getControlledEntityId()
    local controlledEntityLevel = controlledEntity:getLv()
    local id = entityModel:getId()

    local view = self:newView(entityModel)
    view:addEventListener(Actor.onStateChanged, handler(self, BattleController.onEntityStateChanged))
    view:addEventListener(Actor.Event_onDeadEnd, handler(self, BattleController.onEntityDeadEnd))
    view:addEventListener(Actor.Event_onReleaseShake, handler(self, BattleController.onSkilReleaseShake))
    view:addEventListener(Actor.Event_onIconChanged, handler(self, BattleController.onEntityIconChanged))
    view:addEventListener(Actor.Event_onClearBuffViews, handler(self, BattleController.onEntityClearBuffViews))
    view:addEventListener(Actor.Event_onScreenBlink, handler(self, BattleController.onScreenBlink))
    view:addEventListener(Actor.Event_onShowDeadTips, handler(self, BattleController.onShowDieEffect))

    view:setControlId(controlledEntityId)

    -- 添加左右两侧的头像
    if not entityModel:getIsFakeNpc()
      and not entityModel:getIsNeutral()
      and not entityModel:isHidingHead() then
        local bEnemy = (entityModel:getTeamId() ~= controlledEntity:getTeamId())
        local playerNode = PlayerNode.create(not bEnemy, id, bEnemy, entityModel:getIsTimeMonster(), entityModel:getNpcKind())
        self.playerNodeIndex = self.playerNodeIndex or 0
        self.playerNodeIndex = self.playerNodeIndex + 1
        playerNode:setIndex(self.playerNodeIndex)
        playerNode:setSpecialHPMax(entityModel:getSpecialHPMax())
        local function showPlayerTips(event)
            self:showPlayerTips(id)
        end
        playerNode:addEventListener(PlayerNode.Event_ShowPlayerTips, showPlayerTips)
        local function hidePlayerTips(event)
            self:onHideSelectTarget()
            view:hidePlayerTips(event)
        end
        playerNode:addEventListener(PlayerNode.Event_HidePlayerTips, hidePlayerTips)
        playerNode:addEventListener(PlayerNode.Event_SetCurrentTarget, handler(self,BattleController.onPlayerNodeSetCurrentTarget))
        view:setPlayerNode(playerNode)
    end

	if not entityModel:getIsFakeNpc()
      and not entityModel:getIsNeutral()
      and not entityModel:isHidingHead()
      and entityModel:isHero() then
		local bEnemy = (entityModel.teamId ~= controlledEntity.teamId)
		if bEnemy then
			entityModel:getFaceSideEnemyIcon(function(iconPath)
                if cc.isAlive(view) then
    				view:setFaceIcon(iconPath)
                end
			end)	
		else	
			entityModel:getFaceSideIcon(function(iconPath)
                if cc.isAlive(view) then
    				view:setFaceIcon(iconPath)
                end
			end)	
		end
	else
		--其他生物走正常的
		entityModel:getFaceSideIcon(function(iconPath)
			if cc.isAlive(view) then
                view:setFaceIcon(iconPath)
            end
		end)		
	end

    local actorType
    if controlledEntityId == id then
        actorType = Enums.BattleActorType.self
        if (not battleModel:isPvpBattle()) and 
            (not battleModel:isKofBattle()) and 
            (not battleModel:isTheatrePve()) and 
            (not battleModel:isDuelBattle()) then
            self:SetMapFocusActor(view)
        end
    elseif entityModel.teamId == controlledEntity.teamId then
        actorType = Enums.BattleActorType.teammate
    elseif entityModel.teamId ~= controlledEntity.teamId then
        actorType = Enums.BattleActorType.enemy
    end

    local isShowMana = false

    local x = LocationConfig:getPosOnEntityLayer(entityModel:getPos())
    local y = self.altitude or 100
    view:setX(x)
    view:setY(y)
    view:setHeight(50 * entityModel:getHeight())
    view:setInitY(y)
    if entityModel:isHero() then
        view:setBaseScale(self.defaultScales.characterScale)
        view.effectScale = 2
        view.buffEffectExScale = 1

    elseif entityModel:isNpc() then
        local isBoss = entityModel:isBoss()
        if isBoss then
            view:setBaseScale(self.defaultScales.bossScale)
            view.effectScale = 2
            local buffSize = tonumber(S("battlebossbuffeffectsize")) or 200
            view.buffEffectExScale = buffSize*0.01

            actorType = Enums.BattleActorType.boss
        else
            view:setBaseScale(self.defaultScales.npcScale)
            view.effectScale = 2
            view.buffEffectExScale = 1
        end
    end
    isShowMana = entityModel.isShowMana
    view:setScale(1.0)
    view:setBubbleLayer(self.entityBubbleLayer)
    view:setWarnningLayer(self.entityWarnningLayer)
    view:setStatebarLayer(self.entityStatebarLayer)

    local zorder = entityModel:getDefaultZOrder()
    self.views[id]=view
    -- 设置表现层的单位ID
    view:setId(id)

    local floatEffectPlayer = view:createFloatEffectPlayer()
    self.entityFrontLayer:addFloatEffectPlayer(id, floatEffectPlayer, zorder)

    view:prepareStatusBar()
    view:setSelectSize(entityModel.selectSize)
    view:setSelectExcursion(entityModel.selectExcursion)
    --设置Actor类型
    view:setActorType(actorType, entityModel:isPartner())
    view:setType(entityModel.type)
    view:setIsShowMana(isShowMana)
    view:setTitleName(entityModel:getName())
    view:setFloatTextVisible(self.actorFloatTextVisible)

    if entityModel.teamId == controlledEntity.teamId then
        view:setIsEnemy(false)
    else
        view:setIsEnemy(true)
    end

    if entityModel:isHero() then
        local basicSkillId = entityModel:getBasicSkillId()
        if basicSkillId then
            local res = GD:queryStanceAction(basicSkillId)
            if res then
                view:setIdleAni(res.idle)
                view:setHurtAni(res.hurt)
            else
                printError("can not find basicSkillId in stance_action table!!!!")
            end
        else
            printError("can not find basicSkill!!!!!")
        end

        local classId = entityModel:getClassId()
        if classId then
            local classIcon = entityModel:getClassIcon(classId)
            view:setClassIcon(classIcon)
        end
    end
    view:setLevelColorBySelfLevel(controlledEntityLevel)
    view:idle()
    if view:isEnemy() then
        if not self.enemyList then
            self.enemyList = {}
        end
        table.insert(self.enemyList,id)
    end

    self:refreshViewLayer(view)
    --print("entity ",v.id,"type",v.type,"pos",view:getPositionX(),view:getPositionY(),"scale",view:getScaleY(),"isVisible",view:isVisible())

    if view:isFakeUnit() then
        view:setFakeUnitCtrlStatusVisible(true)
    end
    --如果是特殊pvp战斗，需要常驻显示角色状态
    if battleModel:isMeleeBattle() or battleModel:isKofBattle() or battleModel:isGuildWarBattle() then
        if view:isHero() and EFFECT_ALL_SHOW then
            view:setPvpCtrlStatusVisible(true)
        end
    end
    return view
end

function BattleController:showEnterBattleFloatText(posX, posY, isBossBattle)
    if self.uiFloatLayer then
        local csbFile = Res.BattleNormalFloatText
        if isBossBattle then
            csbFile = Res.BattleBossFloatText
        end
        local effect = display.playCSBAni(csbFile,{autoRemove=true, cb = handler(self,BattleController.showBattleTargetTips)})
        if effect then
            self.uiFloatLayer:addChild(effect)
            effect:setPosition(posX, posY)
        end
    end
end

function BattleController:showBattleTargetTips()
    -- if self.mBattleUIView then
    --     self.mBattleUIView:checkShowBattleTargetTips()
    -- end
end

function BattleController:showPlayerTips(id)
    local view = self.views[id]

    local battleModel = self.model
    local controlledEntity = battleModel:getControlledEntity()

    local viewEntityModel = battleModel:getEntityModelById(view:getUnitModelId())

    local isOtherTeam = viewEntityModel and controlledEntity and viewEntityModel.teamId ~= controlledEntity.teamId

    -- local data = {id = id, name = view:getName(), level = view.mLevel, className = self.mClassName, buffList = view.buffIconDict, isOtherTeam = isOtherTeam, isLocked = view.isLocked}
    --self.mBattleUIView:showPlayerTips(data)
end

function BattleController:onActorEnterEnd()
    self.mActorEnterEnd = true
    self:showAllUI()
end

function BattleController:calculateBoundary()
    local maxPosX = 0
    local centerPos = self.startPixel + (display.width*self.screenScale/2.0)
    for k,v in pairs(self.views) do
        local id = v:getId()

        if not v:isDead() then
            -- print("--------------v:getPositionX():"..v:getPositionX())

            -- local box = v:getBoundingBox()
            -- local viewPos = v:getPositionX()
            -- local x1 = viewPos + box.x
            -- local x2 = x1 + box.width
            -- local posx1 = math.abs(centerPos - x1)
            -- local posx2 = math.abs(centerPos - x2)
            -- local posx = math.max(posx1, posx2)

            local posx1,posx2 = v:getLeftRightPos()
            local posx = math.max(math.abs(centerPos - posx1), math.abs(centerPos - posx2))

            -- local posx = math.abs(centerPos - v:getPositionX())
            if maxPosX < posx then
                maxPosX = posx
            end
        end
    end
    return maxPosX
end

function BattleController:focusOnMyself()
    -- 小地图定位到当前玩家的视野
    if self.model:isMeleeBattle() or self.model:isZombieBattle() then
        local controlledEntityId = self.model:getControlledEntityId()
        local selfView = self:getEntityView(controlledEntityId)
        self:SetMapFocusActor(selfView)
    end
end

function BattleController:getControlledView()
    local controlledEntityId = self.model:getControlledEntityId()
    return self:getEntityView(controlledEntityId)
end


function BattleController:onSelectSkill(event)
    self:focusOnMyself()
    local skillId = event.skillId
    local posX = event.posX
    self.selectedSkill = skillId
    self.selectedSubSkill = event.subSkillId
    self.itemInstanceId = event.instanceId
    local skillCfg = self.model.mBattleLoop:getSkillConfig(skillId)
    local targetKind = skillCfg:getTargetKind()
    if targetKind == Enums.TargetKind.Point then
        --如果是point todo
    else
        local isTargetSelectionNeeded = self.model.mBattleLoop:targetSelectionNeeded(skillCfg)
        if isTargetSelectionNeeded then
            --需要选择目标的
            local targetUnits = self:getTargetUnitsBySkill(skillId)
            if targetUnits then
                local currentPlayerTargetId = self.targetId
                local isCurrentPlayerTargetCanBeSkillTarget = false
                for k,v in pairs(targetUnits) do
                    if v:getId() == currentPlayerTargetId then
                        isCurrentPlayerTargetCanBeSkillTarget = true
                        break
                    end
                end
                if isCurrentPlayerTargetCanBeSkillTarget then
                    if self.model:myNextBasicTargetId() == 0 then
                        self.model:setSkillTarget(currentPlayerTargetId)
                    end
                    self:tryToApplySelectedSkill()
                else
                    self:onForceLockTarget(false)
                    local targetId = self:getDefaultTarget(skillId)
                    if targetId then
                        self:setTarget(targetId, true)
                        self:tryToApplySelectedSkill()
                    elseif not self.isGameOver then
                        --周围没有目标提示
                        app:popMessage("fight_battle_notargetaround_18", nil, nil, Enums.ToastTag.battle)
                        if currentPlayerTargetId > 0 then
                            self:clearTarget(true)
                        end
                    end
                end
            end
        else
            self:tryToApplySelectedSkill()
        end
    end
end

function BattleController:onFinishChantCharge(event)
    local skillId = event.skillId
    self.model:onInputFinishChantCharge(skillId)
end

function BattleController:getControllerLogicPos()
    local battleModel = self.model
    local controlledEntityId = battleModel:getControlledEntityId()
    local unit = self.model.mBattleLoop:getEntityById(controlledEntityId)
    return Entity.pos(unit)
end

--获取targetPoint 点的逻辑坐标， dis 是距离主角的位置 damageRange是当前技能的伤害范围, defaultPos是目标的位置，如果为nil则以主角位置为准
function BattleController:getCheckedTargetPoint(dis, damageRange, defaultPos)
    --释放点的逻辑位置
    local pos
    if defaultPos then
        pos = defaultPos + dis
    else
        pos = self:getControllerLogicPos() + dis
    end

    local mapSize = self.locationCount
    if pos - damageRange < 0 then
        pos = damageRange
    elseif pos + damageRange > mapSize then
        pos = mapSize - damageRange
    end
    return pos
end

function BattleController:onPointSkillRelesed(event)
    local skillId = event.skillId
    local moveDis = event.moveDis
    local damageRange = event.damageRange
    self.selectedSkill = skillId

    --point判断战场内
    local point = self:getCheckedTargetPoint(moveDis, damageRange, event.pos)

    self.selectedPoint = point
    self:tryPointAndSkill()
    self:onPointSkillHideEffect()
end

function BattleController:onPointSkillShowEffect(event)
    if self.pointSkillEffect then
        self.pointSkillEffect:setVisible(true)
    else
        self.pointSkillEffect = display.newArmature({path="armatures/effect/zhidingzuobiaofanwei",armatureName="zhidingzuobiaofanwei",animationName="",skeletonName="zhidingzuobiaofanwei", async = false,})
        self.pointSkillEffect:getAnimation():gotoAndPlay("fanwei")
        self.backLayer:addChild(self.pointSkillEffect)
    end

    local moveDis = event.moveDis
    local damageRange = event.damageRange

    --特效大小缩放
    if damageRange > 0 then
        if self.pointSkillDamageRanageCache ~= damageRange then
            self.pointSkillDamageRanageCache = damageRange
            local width = LocationConfig:getWidthOnEntityLayer(damageRange)*2
            self.pointSkillEffect:setScale(1.0)
            local box = self.pointSkillEffect:getBoundingBox()
            local scale = width/(box.width*LocationConfig:getScreenScale())
            self.pointSkillEffectScaleCache = scale
            self.pointSkillEffect:setScale(scale)
        else
            self.pointSkillEffect:setScale(self.pointSkillEffectScaleCache)
        end
    else
        self.pointSkillEffect:setScale(1.0)
    end

    --释放点的逻辑位置
    local pos = self:getCheckedTargetPoint(moveDis, damageRange, event.pos)
    local posX = LocationConfig:getPosOnEntityLayer(pos)
    self.pointSkillEffect:setPositionX(posX)
end

function BattleController:onPointSkillHideEffect()
    if self.pointSkillEffect then
        self.pointSkillEffect:setVisible(false)
    end
end

function BattleController:getTargetUnitsBySkill(skillId)
    local selectSkill = self:mySkill(skillId)
    local targets
    if selectSkill then
        targets = selectSkill:getEligibleTargets()
    end
    return targets
end

function BattleController:getDefaultTarget(skillId)
    local selectSkill = self:mySkill(skillId)
    local targets = selectSkill:getEligibleTargets()
    local sortType = selectSkill:targetSortType()

    local battleModel = self.model
    local controlledEntityId = battleModel:getControlledEntityId()
    local selfView = self:getEntityView(controlledEntityId)
    local posX = 0
    if cc.isAlive(selfView) then
        posX = selfView:getPositionX()
    else
        return
    end
    
    return self:getTargetIdBySortRule(targets, selfView, posX, sortType)
end

-- 根据规则类型筛选目标
function BattleController:getTargetIdBySortRule(targets, selfView, selfPosX, sortType)
    local posX = selfPosX
    local id
    local targetView
    local targetPosX
    local dis
    local inFaceDir --是否在角色的前面上
    local isChangeData
    local targetParam = {}
    for k, v in pairs(targets) do
        id = Entity.getId(v)
        targetView = self.views[id]
        if targetView then
            targetPosX = targetView:getPositionX()
            isChangeData = false
            inFaceDir = false
            if selfView.dir == -1 then
                --如果朝左
                if targetPosX - posX <= 0 then
                    inFaceDir = true
                end
            else
                --如果朝右
                if targetPosX - posX >= 0 then
                    inFaceDir = true
                end
            end
            if sortType == Enums.TargetSortType.TargetSort_Nearer then
                dis = math.abs(targetPosX - posX)
            elseif sortType == Enums.TargetSortType.TargetSort_HpLowerPercent then
                dis = Unit.hpPercent10K(v)
                inFaceDir = true
            else
                dis = 0
            end

            if not targetParam.targetId then
                --如果还没有数据
                isChangeData = true
            else
                if targetParam.inFaceDir == inFaceDir then
                    --如果是同样的方向，比较距离
                    if dis < (targetParam.minDistance or 0) then
                        isChangeData = true
                    end
                else
                    --如果不是同样的方向，比较方向
                    if inFaceDir then
                        isChangeData = true
                    end
                end
            end
            if isChangeData then
                targetParam.minDistance = dis
                targetParam.targetId = id
                targetParam.inFaceDir = inFaceDir
            end
        end
    end

    return targetParam.targetId
end

function BattleController:getTargetsEntitys(targets)
    local battleModel = self.model

    local entities = {}
    for k,v in pairs(targets) do
        local data = {
            targetId = 0,
            posX = 0,
            hp = 0,
            hpPercent = 0,
            iconFile = "art/face_icon/default.png",
            actorType = Enums.BattleActorType.enemy,
            name = "missing",
            classIcon = "art/class_icon/class_701.png",
            npcId = 0,
        }

        local target = v
        local id = target:getId()
        local view = self:getEntityView(id)
        local entityModelId = view:getUnitModelId()
        local entity = self:getEntityModelById(entityModelId)
        --print("--------------------v.firstTargetId:"..v.firstTargetId)

        if target and entity then
            data.targetId = id
            data.posX = view:getPositionX()
            local hp = target:hp()
            local hpMax = target:hpMax()
            data.hp = hp
            data.hpPercent = hp*100/hpMax
            data.iconFile = entity:getFaceSideIcon()
            data.actorType = view:getActorType()
            data.name = view:getName()
            data.classIcon = view:getClassIcon()
            data.npcId = entity:getNpcId() or 0
            if entity:isHero() then
                data.headId = entity.headId
            end

            entities[#entities+1] = data
        end
    end
    return entities
end

function BattleController:mySkills()
    local skills = self.model:mySkills()
    return skills
end

function BattleController:mySkill(skillId)
    local skill = self.model:mySkill(skillId)
    return skill
end

function BattleController:tryPointAndSkill()
    local isSuccess = false
    if self.model then
        isSuccess = self.model:tryPointAndSkill(self.selectedPoint, self.selectedSkill)
        if isSuccess then
            --clear
            self:clearTarget(false)
            self.selectedPoint = nil
            self.selectedSkill = nil
        end
    end
end

function BattleController:tryToApplySelectedSkill()
    local isSuccess = false
    if self.model then
        isSuccess = self.model:tryToApplySkill(self.targetId, self.selectedSkill, self.itemInstanceId, self.selectedSubSkill)
        if isSuccess then
            --clear
            self.selectedSkill = nil
            self.itemInstanceId = nil
            self.selectedSubSkill = nil
        end
    end

    return isSuccess
end

--点击目标之后的处理
function BattleController:onShowSelectTarget(event)
    local targetId = event.targetId
    local view = self.views[targetId]
    --显示选择目标的特效 其他的角色隐藏选择特效
    for k,v in pairs(self.views) do
        if targetId == v:getId() then
            v:setSelected()
        else
            v:setUnSelected()
        end
    end
end

--隐藏所有选择目标的特效
function BattleController:onHideSelectTarget(event)
    for k,v in pairs(self.views) do
        v:setUnSelected()
    end
end

function BattleController:initSkillPanel(controlledEntity, id)
    if not controlledEntity then
        return
    end
    local controlledSkills = controlledEntity:getControlledSkills()
    local normalSkill = controlledEntity:getNormalSkill()
    local rollSkill = controlledEntity:getRollSkill()
    local legendSkill = controlledEntity:getLegendSkill()
    local classID = controlledEntity:getClassId()
    local unit = self.model.mBattleLoop:getEntityById(id)
    --初始化SKILL界面
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SKILL_INIT, unit, classID, normalSkill, controlledSkills, rollSkill, legendSkill)
    if app:isBattleGuideComp() then
        self.mNewBattleUIView.bottomView.skillPanelView:showSkillBtnName()
    end
end

function BattleController:onEntityIconChanged(view,iconPath)
    local viewId = view:getId()

    --self.mBattleUIView:setTargetIconPath(viewId, iconPath)
end

function BattleController:onEntityClearBuffViews(buffList)
    for _,buffView in pairs(buffList) do
        self.visualEffect:removeEffect(buffView)
    end
end

function BattleController:onEntityStateChanged(view,from,to, extra)

    local viewId = view:getId()
    local entityModelId = view:getUnitModelId()
    local model = self:getEntityModelById(entityModelId)

    if to == Enums.CharacterState.dead then
        -- local deadColor = cc.c3b(self.deadColor.r,self.deadColor.g,self.deadColor.b)
        -- view:playDead(nil, model.deathSound,deadColor)

        --一方最后一个单位死亡
        if self:isOwnerLastEntity(viewId) then
            --隐藏ui
            --self.mBattleUIView:setVisible(false)
            --隐藏主角头上跳字
            -- for k,v in pairs(self.views) do
            --     -- v:hideAllFloatEffect()
            -- end

            --slow effect when dead
            self:dispatchEvent("LastEntityDie")

            local scheduler = cc.Director:getInstance():getScheduler()
            scheduler:setTimeScale(0.1)
            local actions = {}
            table.insert(actions,cc.DelayTime:create(0.15))
            table.insert(actions,cc.CallFunc:create(function()
                self.isLastEntityActionRun = false
                scheduler:setTimeScale(1)
                self:dispatchEvent("LastEntityDieEnd")
            end))
            self:scheduleOnce(cc.Sequence:create(actions))
            self.isLastEntityActionRun = true
        end
    elseif to == Enums.CharacterState.chant then -- 进入吟唱
        if not self._newerBattleGuideEndedFlag then -- 新手战引导未结束？
            local skillId = skillInterface.id( extra )
--            print( " ---------------->>>>>>>> 新手战引导 进入吟唱", skillId )
            NewerbattleguideController:triggerBattleGuideEvent( skillId, "enter-chant" )
        end
    end
end

function BattleController:onShowDieEffect()
    if self.model:isMeleeBattle() or self.model:isZombieBattle() then
        local posX = display.width/2.0
        local posY = display.height/2.0
        if self.uiFloatLayer then
            local dieEffect = display.playCSBAni(Res.BattlePvPDieFloatText,{autoRemove=true, cb = function()
            end})
            self.uiFloatLayer:addChild(dieEffect)
            dieEffect:setPosition(posX,posY)
        end
    end
end

function BattleController:onEntityDeadEnd(id)
    -- 删除单位的表现
    self.entityFrontLayer:removeFloatEffectPlayer(id)
    self.views[id] = nil
end

--是否为一方最后一个单位
function BattleController:isOwnerLastEntity(viewId)
    --todo 有些战斗会先全死亡，再召唤怪，先屏蔽改功能
    return false

    -- local view = self.views[viewId]
    -- for id,v in pairs(self.views) do
    --     if id == viewId then
    --     elseif v.initDir == view.initDir and v:isAlive() then
    --         return false
    --     end
    -- end
    -- return true
end


function BattleController:checkBattleState()
    self:dispatchEvent("checkBattleState")
end

function BattleController:onSetNextUpdateTime(time)
    self.visualEffect:setNextUpdateTime(time)
end

function BattleController:onConnectDelay()
    self:dispatchEvent("ConnectDelay")
end

function BattleController:getViewByID(id)
    return self.views[id]
end

function BattleController:onEnterBattle()
    local battleModel = self.model

    if battleModel:isPvpBattle() or battleModel:isMeleeBattle() or battleModel:isTheatrePve() or battleModel:isDuelBattle() then
        -- local posX,posY = self.mNewBattleUIView:getBossFloatTextPos()
        -- if (not posX) or (not posY) then
        --     posX = display.width/2.0
        --     posY = display.height/2.0
        -- end

        local posX = display.width/2.0
        local posY = display.height/2.0
        if self.uiFloatLayer then
            local csbFile = Res.BattlePvPBeginFloatText
            local effect = cc.CSLoader:createNode(Res.BattlePvPBeginFloatText,false,true)
            if effect then
                self.uiFloatLayer:addChild(effect)
                effect:setPosition(posX, posY)
                local actions = {}
                table.insert(actions,cc.DelayTime:create(1))
                table.insert(actions,cc.CallFunc:create(function()
                    local timeEffect = display.playCSBAni(Res.BattlePvPTimeFloatText,{autoRemove=true, cb = function()

                    end})
                    self.uiFloatLayer:addChild(timeEffect)
                    timeEffect:setPosition(posX, posY)

                    effect:removeFromParent()
                end))
                local action = cc.Sequence:create(actions)
                effect:runAction(action)
            end
        end
    elseif battleModel:isLionBattle()  then
        -- or battleModel:isZombieBattle()
        --显示回合数
        local roundNums = battleModel.roundNums
        local roundNumsStr = string.format(L("roundText"), roundNums)
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_FMTION, roundNumsStr)
        --显示击杀头像
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SHOW_LION_KILL_LIST)
    end
end

-- pvp 锦标赛结果界面
function BattleController:showPvpResultView(isWin, isMeleeBattle)
    print("BattleController:showPvpResultView", isWin)
    local panelName = isWin and "openWinView" or "openFailView"
    local panelChampionName = isWin and "openChampionWinView" or "openChampionFailView"

    -- pvp玩法的回调
    local funcPvp = function()
        if isMeleeBattle then
            app:dispatchEvent({name="FORCE_QUIT"})
        end

        MapManager:setNextChangeMapIgnoreAni(true)
        app.session:request("pb_map.C2S_BackToLastMap",{})

        app:dispatchEvent({name="EVENT_BATTLE_PVP_END"})
        
        MapManager:setChangeMapOverCB(function()
            app:sendMsg("PvpController", "openView")
        end)
    end

    -- 冠军赛的回调
    local funcThrone = function()
        app.session:request("pb_throne.C2S_EnterThroneMap", {}) -- 直接发送进入准备场

        app:dispatchEvent({name="EVENT_BATTLE_PVP_END"})
    end

    local funcCSGuildWar = function()
        app:dispatchEvent({name="EVENT_BATTLE_PVP_END"})
        EM:notify(ViewEvent.CSGuildWar_LeaveBattle)
    end

    -- TODO：跨服公会战结算
    if self.model:getBattleType() == Enums.EBattleType.BtType_Throne then
        app:sendMsg("PvpController", panelChampionName, nil, funcThrone)
    elseif self.model:getBattleType() == Enums.EBattleType.BtType_WorldGuildWar then
        -- app:sendMsg("PvpController", panelName, nil, funcCSGuildWar)
        funcCSGuildWar()
    else
        app:sendMsg("PvpController", panelName, nil, funcPvp)
    end

end

function BattleController:onGameOver(event)
    if self.isGameOver then
        debugLog("self.isGameOver is already true!")
        return
    end

    -- 还需要断开链接
    self:exitBattle()

    --关闭商店
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.HIDE_BATTLE_SHOP)

    --关闭战斗中的聊天框
    local isWin = event and event.isWin or false
    local controlledEntityId = self.model:getControlledEntityId()
    local selfView = self:getEntityView(controlledEntityId)
    local victoryDir = event and event.victoryDir or 0
    local isEscapeBattle = event and event.isEscapeBattle or false
    local isMeleeBattle = self.model:isMeleeBattle()
    -- PVP竞技场和赤道大乱斗有特殊结果界面
    if self.model:isPvpBattle() or isMeleeBattle then
        -- mvp 当前只在pvp和melee里面有mvp
        local function callback()
            local mvpId = self.model.mBattleLoop:getMvpUnitId()
            local mvpView
            if mvpId then
                mvpView = self:getViewByID(mvpId)
            end
            if mvpView then
                mvpView:setMVP(true)
                self:focusEntityMVP()
                self:SetMapFocusActor(mvpView)
                self:setAlreadAttack(false)
                MapManager:getMap():setMapAdjudtX(0)
                MapManager:getMap():setMapAdjustSpeed(Constant.BattleCameraMaxSpeed)
                local currentScale = MapManager:getMapScale()
                MapManager:forceCameraZoomToDest({dstScale = 1.3,time = math.abs(mvpView:getPositionX()-selfView:getPositionX())/1000,call = function()
                    if cc.isAlive(self.mvpShowLayer) then
                        self.mvpShowLayer:setVisible(true)
                    end
                    if cc.isAlive(mvpView) then
                        display.setColor(mvpView,cc.c3b(255,255,255))
                        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MVP_SHOW,mvpView:getName(),mvpView:isOurTeam(),mvpView)

                        mvpView:playMVPVictory(self.startPixel,self.screenScale)
                        self:performWithDelay(function()
                            self:showPvpResultView(isWin,isMeleeBattle)
                            MapManager:forceCameraZoomToDest({dstScale = currentScale,time = 0.0,call = function()end})
                        end, 4.5)
                    end
                end})
            else
                self:showPvpResultView(isWin,isMeleeBattle)
            end
        end

        --清除复活界面
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_SHOW_PVP_REVIVE,{reviveSelfTimes = 0})

        self.mNewBattleUIView:play("hide")

        if isWin then
            --播放胜利特效
            self.mNewBattleUIView:showWinEffect(true,callback)
        else
            --播放失败特效
            self.mNewBattleUIView:showLoseEffect(true,callback)
        end
    else
        self:displayAllUI(false)
        self:playEntityVictory(victoryDir,isEscapeBattle)
    end

    if self.visualEffect then
        self.visualEffect:stop()
    end

    if self.dbmMgr then
        self.dbmMgr:clear()
    end


    self.isGameOver = true
    self.cameraMoveDelay=Constant.BattleCameraMoveDelay
    --停止移动
    for k,v in pairs(self.views) do
        v:setFloatTextVisible(false)
        v:setGameOverCtrlStatusVisible(true)
        v:stopRunToAction()
        v:clear()
    end

    local playerMoved = 0
    if selfView then
        playerMoved = selfView:getPositionX() - self.mainCharacterPosX
    end

    self:stopMusic()
    self:dispatchEvent("GameResult",isWin,playerMoved)
end

function BattleController:onFocusPos(posx, needInit)
    if not self.focusNode then
        self.focusNode = display.newNode()
        self.entityLayer:addChild(self.focusNode)
    end

    self.focusNode:setPositionX(posx)
    self:SetMapFocusActor(self.focusNode, needInit)
end

function BattleController:SetMapFocusActor(actor, needInit)
    self:dispatchEvent("SetMapFocusActor", actor, needInit)
end

--释放效果
function BattleController:showMaskForReleaseEffect(showMaskLevel)
    if showMaskLevel == 1 then
        self:dispatchEvent("EnemySuperSkillRelease")
    elseif showMaskLevel == 2 then
        self:dispatchEvent("SuperSkillRelease")
    end

    -- local actions = {}
    -- table.insert(actions,cc.DelayTime:create(1))
    -- table.insert(actions,cc.CallFunc:create(function()
    --     self:dispatchEvent("RecoverMapColor")
    -- end))
    -- self:scheduleOnce(cc.Sequence:create(actions))
end

function BattleController:hideMaskForReleaseEffect()
    self:dispatchEvent("RecoverMapColor")
end

function BattleController:setMapFullBlack()
    self.mapFullBlack = true
    self.sceneMaskLayer:setVisible(false)
    self:dispatchEvent("MapFullBlack")
end

function BattleController:removeMapFullBlack()
    --print("==========removeMapFullBlack===========")
    self.mapFullBlack = false
    self.sceneMaskLayer:setVisible(true)
    self:dispatchEvent("RecoverMapColor")
end

function BattleController:setFrog(bFrog)
    self.sceneMaskLayer:setVisible(bFrog)
end


function BattleController:showComboEffect(b)
    --self.mBattleUIView:showComboEffect(b)
end

function BattleController:entitySkillInterrupted(event)
    local casterId = event.casterId
    local targetId = event.targetId
    local skillId = event.skillId

    local battleModel = self.model
    local controlledEntity = battleModel:getControlledEntity()
    local controlledEntityId = battleModel:getControlledEntityId()

    local casterView = self:getEntityView(casterId)
    local casterEntityModel = nil
    if casterView then
        casterEntityModel = battleModel:getEntityModelById(casterView:getUnitModelId())
    end
    local targetView = self:getEntityView(targetId)
    local targetEntityModel = nil
    if targetView then
        targetEntityModel = battleModel:getEntityModelById(targetView:getUnitModelId())
    end

    local isOwnerPartnerCast = casterEntityModel and casterEntityModel:isPartner() and casterEntityModel.teamId == controlledEntity.teamId
    local isOwnerPartnerTarget = targetEntityModel and targetEntityModel:isPartner() and targetEntityModel.teamId == controlledEntity.teamId
    local isAboutOwnerPartner = isOwnerPartnerCast or isOwnerPartnerTarget

    -- local isShowAllDamage = UD.setting:isShowAllDamage()

    local isAboutMe = casterId == controlledEntityId or targetId == controlledEntityId

    --只显示与自己相关的
    -- if not isShowAllDamage then
        if (not isAboutMe) and (not isAboutOwnerPartner) then
            return
        end
    -- end


    -- local view = self:getEntityView(casterId)
    -- local bySelf = event.bySelf
    -- local showText = event.showText

    -- if (not bySelf) and showText then
    if casterView then
        casterView:pushInterrupedFloatEffect(casterView:isSelfTeam())
    end
    -- end
end

function BattleController:entitySkillCancelByNoMana(event)
    local casterId = event.casterId
    local targetId = event.targetId
    local skillId = event.skillId

    local battleModel = self.model
    local controlledEntityId = battleModel:getControlledEntityId()

    -- local casterView = self:getEntityView(casterId)
    -- local casterEntityModel = nil
    -- if casterView then
    --     casterEntityModel = battleModel:getEntityModelById(casterView:getUnitModelId())
    -- end

    local isAboutMe = casterId == controlledEntityId

    if isAboutMe then
        app:popMessage("fight_battle_error_02", nil, nil, Enums.ToastTag.battle)
    end
end

function BattleController:onEntityHurt( event, sBasicAttack)
    local params = battle.EvtOnHitParam.getHitPar( event )
    local buffCasterId = params:getBuffCasterId()
    local fromId = params:getCasterId()
    local toId = params:getTargetId()
    local damage = params:getDamage()
    local isMiss = params:getIsMiss()
    local isCritical = params:getIsCritical()
    local isBlocked = params:getIsBlocked()
    local isLimited = params:getIsLimited()
    local hitType = params:getHitType()
    local shake = params:getShake()
    local leechHP = params:getLeechHP()
    local isTargetInStealth = params:getIsTargetInStealth()

    local casterSummonerId = params:getCasterSummonerId()
    local targetSummonerId = params:getTargetSummonerId()

    local battleModel = self.model
    local controlledEntity = battleModel:getControlledEntity()
    local controlledEntityId = battleModel:getControlledEntityId()

    local casterView = self:getEntityView(fromId)
    local casterEntityModel
    if casterView then
        casterEntityModel = battleModel:getEntityModelById(casterView:getUnitModelId())
    end
    local targetView = self:getEntityView(toId)
    local targetEntityModel
    if targetView then
        targetEntityModel = battleModel:getEntityModelById(targetView:getUnitModelId())
    end

    local isOwnerPartnerCast = casterEntityModel and casterEntityModel:isPartner() and casterEntityModel.teamId == controlledEntity.teamId
    local isOwnerPartnerTarget = targetEntityModel and targetEntityModel:isPartner() and targetEntityModel.teamId == controlledEntity.teamId
    local isAboutOwnerPartner = isOwnerPartnerCast or isOwnerPartnerTarget

    local isAboutMeSummoner = casterSummonerId == controlledEntityId or targetSummonerId == controlledEntityId

    -- local controlledEntityId = self.model:getControlledEntityId()
    local isAboutMe = fromId == controlledEntityId or toId == controlledEntityId or buffCasterId == controlledEntityId

    local isTargetSelf = toId == controlledEntityId
    local isCasterSelf = fromId == controlledEntityId

    local isTargetSelfTeam = false
    local isCasterSelfTeam = false
    if targetView then
        isTargetSelfTeam = targetView:isSelfTeam()
    end
    if casterView then
        isCasterSelfTeam = casterView:isSelfTeam()
    end

    -- local isShowAllDamage = UD.setting:isShowAllDamage()

    --shake
    if targetView then
        if damage ~= 0 then
            if isAboutMe then
                self:skillHitShake(shake)
            end
        end
    end

    --只显示与自己相关的
    -- if not isShowAllDamage then
        if (not isAboutMe) and (not isAboutOwnerPartner) and (not isAboutMeSummoner) then
            return
        end
    -- end

    -- 敌方隐身单位不显示伤害跳字
    if targetEntityModel and targetEntityModel.teamId ~= controlledEntity.teamId and isTargetInStealth then
        return
    end

    local view = targetView
    if view then
        if damage ~= 0 then
            view:pushDamageFloatEffect(damage,isCritical, isBlocked, isTargetSelfTeam, isLimited)
            if isAboutMe then
                view:showFlashHurtEffect()
            end
        elseif isMiss then
            view:pushMissFloatEffect(view:isSelfTeam())
        elseif hitType == 1 then
            -- 吸收
            -- print("==========吸收===========")
            view:pushAbsorbFloatEffect(view:isSelfTeam())

            local dir = view:facing()
            local ret,posX,posY = view:getBuffHitLocalPos()
            if ret then
                --找到buff打击点 才创建特效
                local Armature = app:getClass("Armature")
                local absorbEffectNode = Armature.create({path="armatures/effect/shieldhit",armatureName="shieldhit",skeletonName="shieldhit"})
                if absorbEffectNode then
                    view:addChild(absorbEffectNode)

                    local scaleX = math.abs(absorbEffectNode:getScaleX())
                    absorbEffectNode:setScaleX(scaleX*-dir)

                    absorbEffectNode:setPosition(posX,posY)
                    absorbEffectNode:playAni({name="shieldhit",fadeInTime=0,playTimes=1,completeCallback=function()
                        absorbEffectNode:removeFromParent()
                    end})
                end
            end
        elseif hitType == 2 then
            --免疫
            view:pushImmunityFloatEffect(view:isSelfTeam(), L("immune_1"))
        end
    end

    --吸血
    local casterView = self.views[fromId]
    --print("======onEntityHurt==fromId",fromId)
    --print("========leechHP",leechHP)
    if casterView then
        if leechHP > 0 then
            casterView:pushDamageFloatEffect(-leechHP, false, false, isCasterSelfTeam)
        end
    end
end

function BattleController:onEntityTalk(time,unitId,text)
    local ltext = L(text)
    local duration = 5

    local view = self.views[unitId]
    if view then
        view:appendBubbleTask({text=ltext,duration=duration})
    end
end

function BattleController:onProjectileBounce(event)
    local projectileId = event.projectileId
    local targetId = event.targetId
    local casterId = event.casterId
    local pos = event.pos

    local targetView = self.views[targetId]
    local casterView = self.views[casterId]
    local projectileView = self.projectileViews[projectileId]
    if projectileView then
        local posX = LocationConfig:getPosOnEntityLayer(pos)
        local projectilePosX = self.entityLayer:toWorldPosition(posX,0)

        local fromNode ,fromBone,fromBindtype = self.effectFactory:getBindingNodeAndBoneFrom(projectileView.fromPlace,projectileView.fromParam, casterView,targetView)
        local toNode ,toBone, toBindtype = self.effectFactory:getBindingNodeAndBoneFrom(projectileView.toPlace,projectileView.toParam, casterView,targetView)
        projectileView:bounceSetting(fromNode ,fromBone,fromBindtype, toNode ,toBone, toBindtype, projectilePosX)
        projectileView:fire(projectilePosX, false)
        local accumulator = self.model.mBattleLoop:getAccumulator()
        projectileView:setAccumulator(accumulator)
    end
end

function BattleController:onEntityTeamMark(event)
    local time = event.time
    local targetId = event.targetId
    local casterId = event.casterId
    local flagId = event.flagId

    local targetView = self.views[targetId]
    local casterView = self.views[casterId]

    if targetView and casterView and flagId then
        local str
        if flagId == Enums.TeamMarkList.NONE then
            str = string.format(L("marktext02"), casterView:getName(), targetView:getName())
        else
            str = string.format(L("marktext01"), casterView:getName(), targetView:getName())
        end
        if str then
            app:sendMsg("IMModel", "addSystemMsg", str, nil, true)
        end
    end
end

function BattleController:onEntityImmuneBuff(event)
    local time = event.time
    local casterId = event.casterId
    local targetId = event.targetId
    local tag = event.tag
    local targetView = self.views[targetId]

    if targetView and tag then
        --是否和我有关的判断
        if not self:isAboutMe(casterId, targetId) then
            return
        end

        local str = L("immune_"..tag)
        targetView:pushImmunityFloatEffect(targetView:isSelfTeam(),str)
    end
end

function BattleController:onEntityRevive(event)
    local time = event.time
    local targetId = event.targetId
    local pos = event.pos
    local targetView = self.views[targetId]

    if targetView and pos then
        targetView:playReviveEffect()
    end

    if targetId == self.model:getControlledEntityId() then
        self:SetMapFocusActor(targetView)
    end
end

function BattleController:onEntitySoulChanged(event)
    local unitId = event.unitId
    local oldSoul = event.oldSoul
    local newSoul = event.newSoul
    local unitView = self.views[unitId]
    if unitView then
        unitView:playSoulChangeEffect(oldSoul, newSoul)
    end
end

function BattleController:onLionBossAppear(event)
    local time = event.time
    if self.model:isLionBattle() then
        --显示 boss 最终回合提示
        local posX,posY = self.mNewBattleUIView:getBossFloatTextPos()
        if (not posX) or (not posY) then
            posX = display.width/2.0
            posY = display.height/2.0
        end

        -- local posX = display.width/2.0
        -- local posY = display.height/2.0
        if self.uiFloatLayer then
            local effect = cc.CSLoader:createNode(Res.BattleLionBossFloatText,false,true)
            if effect then

                effect:findChild("Sprite/name"):setString(L("lionheart_RoundFinalTips"))
                effect:findChild("Sprite/tips"):setString(L("lionheart_BossComingSoonTips"))

                self.uiFloatLayer:addChild(effect)
                effect:setPosition(posX, posY)
                local actions = {}
                table.insert(actions,cc.DelayTime:create(1))
                table.insert(actions,cc.CallFunc:create(function()
                    effect:removeFromParent()
                end))
                local action = cc.Sequence:create(actions)
                effect:runAction(action)
            end
        end
    end
end

function BattleController:onLionRefreshKillList(event)
    local killList = self.model.mBattleLoop:getKillList()
    if killList then
        local isThreeKill = true
        local tempNpcId = nil
        local iconPaths = {}
        for k,npcId in pairs(killList) do
            if tempNpcId == nil then
                tempNpcId = npcId
            elseif tempNpcId ~= npcId then
                isThreeKill = false
            end
            local res = GD:queryNpcRes(npcId)
            local iconPath = ""
            if res and res.face then
                iconPath = Res.npcIconPath..res.face..".png"
                table.insert(iconPaths, iconPath)
            end
        end

        if table.nums(killList) < 3 then
            isThreeKill = false
        end
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_REFRESH_KILLLIST, iconPaths, isThreeKill)
    end
end

-- function BattleController:test()
--     print("===========:test()==============")
--     if not self.killList then
--         self.killList = {}
--     end
--     if table.nums(self.killList) == 0 then
--         self.killList = {23100007}
--     elseif table.nums(self.killList) == 1 then
--         self.killList = {23100007,23100007}
--     elseif table.nums(self.killList) == 2 then
--         self.killList = {23100007,23100007,23100007}
--     elseif table.nums(self.killList) == 3 then
--         self.killList = {23100012,23100007,23100007}
--     end
--     dump(self.killList, "self.killList", 6)
--     local killList = self.killList
--     if killList then
--         local isThreeKill = true
--         local tempNpcId = nil
--         local iconPaths = {}
--         for k,npcId in pairs(killList) do
--             if tempNpcId == nil then
--                 tempNpcId = npcId
--             elseif tempNpcId ~= npcId then
--                 isThreeKill = false
--             end
--             local res = GD:queryNpcRes(npcId)
--             local iconPath = ""
--             if res then
--                 iconPath = Res.npcIconPath..res.face..".png"
--             end
--             table.insert(iconPaths, iconPath)
--         end

--         if table.nums(killList) < 3 then
--             isThreeKill = false
--         end
--         dump(iconPaths, "iconPaths", 6)
--         BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_REFRESH_KILLLIST, iconPaths, isThreeKill)

--         if table.nums(self.killList) == 3 and not isThreeKill then
--             self.killList = {23100007}
--         end
--     end
-- end

function BattleController:onBattleStart(event)
    local time = event.time
    if self.model:isPvpBattle() or self.model:isKofBattle() or self.model:isTheatrePve() or self.model:isDuelBattle() then
        local controlledEntityId = self.model:getControlledEntityId()
        local selfView = self:getEntityView(controlledEntityId)
        self:SetMapFocusActor(selfView)
    end

    if (self.model:isMeleeBattle() or self.model:isZombieBattle()) and EFFECT_ALL_SHOW then
        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SHOW_MELEE_MAP)
    end

    if self.dbmMgr and UD.setting:isShowDBM() then
        self.dbmMgr:onBattleStart()
    end

end

function BattleController:onBattleRoundPrepare(event)
    local time = event.time
    local round = event.round
    if self.model:isKofBattle() then
        -- BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SHOW_BLACK_SCREEN, false)
        self:showBlackScreen(false)
        self:SetMapFocusActor(nil, true)

        if self.roundPrepareEffectShowing then
            return
        end

        self.roundPrepareEffectShowing = true
        local posX = display.width/2.0
        local posY = display.height/2.0
        if self.uiFloatLayer then
            local csbFile = Res.BattlePvPBeginFloatText
            local effect = cc.CSLoader:createNode(Res.BattlePvPBeginFloatText,false,true)
            if effect then
                local textNode = effect:findChild("Sprite/text")
                if textNode and round then
                    textNode:setString(string.format(L("roundText"), round))
                end
                self.uiFloatLayer:addChild(effect)
                effect:setPosition(posX, posY)
                local actions = {}
                table.insert(actions,cc.DelayTime:create(1))
                table.insert(actions,cc.CallFunc:create(function()
                    local timeEffect = display.playCSBAni(Res.BattlePvPTimeFloatText,{autoRemove=true, cb = function()
                        self.roundPrepareEffectShowing = false
                    end})
                    self.uiFloatLayer:addChild(timeEffect)
                    timeEffect:setPosition(posX, posY)

                    effect:removeFromParent()
                end))
                local action = cc.Sequence:create(actions)
                effect:runAction(action)
            end
        end

        BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_KEEPBKIL,{isKeep = UD.setting:isKeepBasicAttack()})
    end
end

function BattleController:showBlackScreen(b)
    -- print("=============BattleUIView:showBlackScreen==========")
    if b and self.blackScreenLayer == nil then
        self.blackScreenLayer = display.newColorLayer(cc.c4b(0, 0, 0, 255))
        self.uiFloatLayer:addChild(self.blackScreenLayer,99)
    end

    if self.blackScreenLayer then
        -- self.blackScreenLayer:setVisible(b)

        if b then
            local action = self.blackScreenLayer:getActionByTag(Enums.CommonActionTag.BattleBlackScreen)
            if not action then
                action = cca.seq({
                    cca.fadeIn(0.6),
                    cca.fadeOut(0.5)
                })
                action:setTag(Enums.CommonActionTag.BattleBlackScreen)
                self.blackScreenLayer:runAction(action)
            end
        end
    end
end

--回合间隙 黑屏
function BattleController:onBattleRoundSpace()
    -- print("===========BattleController:onBattleRoundSpace===============")
    if self.model:isKofBattle() then
        -- BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.SHOW_BLACK_SCREEN, true)
        self:showBlackScreen(true)
        self:SetMapFocusActor(nil, true)
    end
end

--是否和我有关的判断
function BattleController:isAboutMe(casterId, targetId)
    return self.model:isAboutMe(casterId, targetId)
end

function BattleController:isAboutMyTarget(casterId, targetId)
    local controlledEntityTargetId = self.targetId
    return casterId == controlledEntityTargetId or targetId == controlledEntityTargetId
end

function BattleController:onShowBuffDesc(event)
    local buffId = event.buffId
    local casterId = event.casterId
    local bearerId = event.bearerId
    local displayDesc = L(event.displayDesc)
    local displaySort = event.displaySort
    --print("=========onShowBuffDesc displayDesc",displayDesc)

    --是否和我有关的判断
    if not self:isAboutMe(casterId, bearerId)  then
        return
    end

    local view = self.views[bearerId]
    if view then
        view:showBufffDisplayDesc(displayDesc, displaySort)
    end
end

function BattleController:onShowBuffBlind(event)
    --致盲效果显示
    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.BATTLE_SHOW_BUFF_BLIND)
end

function BattleController:playEntityEntrance(isFirstRound,callback)
--todo
end

function BattleController:focusEntityMVP()
    for _,view in pairs(self.views) do
        --clear state skillEvent
        view:hideState()
        if view:isMVP() then
            view:changeToFrontLayer()
        else
            view:setVisible(false)
        end
    end
end

function BattleController:playEntityVictory(dir,isEscapeBattle)
    for _,view in pairs(self.views) do
        -- local view = self.views[v.id]
        local entityModel = self:getEntityModelById(view:getUnitModelId())
        if view:isAlive() then
            if entityModel:getDir() == dir then
                view:playVictory(self.startPixel,self.screenScale)
            else
                if isEscapeBattle then
                    --如果是逃跑方
                    view:playEscape(self.startPixel,self.screenScale)
                else
                    -- 不是逃跑，播放失败动作
                    view:playFailure()
                end
            end
        end
    end
end

function BattleController:pauseBattle()
    for _,v in pairs(self.views) do
        v:pause()
        -- v:updateViewStatus()
    end
    self.backLayer:pause()
    self.effectFactory:pause()
end

function BattleController:resumeBattle()
    for _,v in pairs(self.views) do
        v:resume()
    end
    self.backLayer:resume()
    self.effectFactory:resume()
end

function BattleController:onBattleEscape()
    local battleModel = self.model
    battleModel:onBattleEscape()
end

function BattleController:onTrainingBattleEscape()
    local battleModel = self.model
    battleModel:onTrainingBattleEscape()
end

function BattleController:onBattleRevive()
    --print("======onBattleRevive====BattleController=========")
    local battleModel = self.model
    battleModel:onBattleRevive()
end

function BattleController:onTeamMark(event)
    local battleModel = self.model
    battleModel:onTeamMark(event)
end

function BattleController:onPlayerTalk(content)
    app:sendMsg("IMModel", "sendTeamMessage", content)
end

--点击角色头像选为当前目标
function BattleController:onPlayerNodeSetCurrentTarget(targetId,isNeedNotifyServer)
    if cc.isAlive(self) and self.views ~= nil then
        local view = self.views[targetId]
        if view and (view:isAlive() or view:getCanRevive()) then
            view:showTouchEndEffect(true)
            -- TODO: 不应该通过表现层数据进行判断
            local myselfView = self:getControlledView()
            if myselfView and not myselfView:isAlive() then
                self:SetMapFocusActor(view)
            else
                self:setTarget(targetId, isNeedNotifyServer)
            end
        end
    end
end

function BattleController:onPlayerMove(event)
    self:focusOnMyself()
    self.model:onPlayerMove(event)
    self.cameraMoveDelay = Constant.BattleCameraMoveDelay
    self:calcCameraMove(0)
end

function BattleController:onPlayerRoll(event)
    self:focusOnMyself()
    self.model:onPlayerRoll(event)
end

function BattleController:onBuyItem(event)
    local battleModel = self.model
    battleModel:onBuyItem(event)
end

function BattleController:onUseItem(event)
    local controlledEntityId = self.model:getControlledEntityId()
    local selfView = self:getEntityView(controlledEntityId)
    if selfView:isDead() then
        return
    end
    self:onSelectSkill(event)
end

function BattleController:interactWithUnit(event)
    local battleModel = self.model
    battleModel:interactWithUnit(event)
end

function BattleController:onTargetLock(event)
    local targetId = event.targetId
    local isLocked = event.isLocked
    local isNeedNotifyServer = event.isNeedNotifyServer
    if isLocked then
        self:setTarget(targetId, isNeedNotifyServer)
    else
        self:clearTarget(isNeedNotifyServer)
    end
end

function BattleController:onRefreshHpBarVisible()
    for k,view in pairs(self.views) do
        view:refreshHpBarVisible()
    end
end

function BattleController:setForceTargetLockedFlag(bFlag)
    self.isForceLocked = bFlag
end

function BattleController:setTarget(targetId, isNeedNotifyServer)
--    print("======> BattleController:setTarget()", targetId, self.targetId, isNeedNotifyServer, self.isForceLocked)
    if self.targetId == targetId then
        --如果当前是目标锁定状态，或者目标没有改变，则不进行操作
        return
    end
    if targetId == 0 then
        self:clearTarget(isNeedNotifyServer)
        return
    end
    local battleModel = self.model
    if not battleModel:isInRangeVision(targetId)  then
        --目标不在视野范围内，不能被选中？
        --进行提示
        app:popMessage("fight_battle_targetisout_19", nil, nil, Enums.ToastTag.battle)
        return
    end
    local previousTargetId = self.targetId
    self.targetId = targetId
    self.targetIdOfTarget = 0
    self.isForceLocked = false
    local targetData
    local targetEntityModel
    local viewTarget

    for id, view in pairs(self.views) do
        if id == targetId then
            targetEntityModel = self:getEntityModelById(view:getUnitModelId())
            viewTarget = view
            view:setCurrentPlayerTargetFlag(true)
        else
            view:setCurrentPlayerTargetFlag(false)
        end
    end

    if isNeedNotifyServer then
        --通知服务器更换目标
        battleModel:setSkillTarget(targetId)
    end

    local controlledEntityId = self.model:getControlledEntityId()
    local controlledEntityModel = self:getEntityModelById(controlledEntityId)

    -- 刷新目标UI
    local targetEntity = self.model.mBattleLoop:getEntityById(targetId)
    if not cc.isDead(targetEntity)
      and self.mNewBattleUIView.topView
      and not targetEntityModel:isHidingHead()
      and not battleModel:isTheatrePve() then
        local targetViewUI = self.mNewBattleUIView.topView.targetView
        targetViewUI:setData(targetEntityModel, viewTarget, targetId, controlledEntityModel:getIsLeader())
        local id = Entity.getId(targetEntity)
        local hp = Unit.hp(targetEntity)
        local hpMax = Unit.hpMax(targetEntity)
        local mana = Unit.mana(targetEntity)
        local manaMax = Unit.manaMax(targetEntity)
        local rage = Unit.rage(targetEntity)
        local rageMax = Unit.rageMax(targetEntity)
        local newEnergy = Unit.energy(targetEntity)
        local newEnergyMax = Unit.energyMax(targetEntity)
        local hpExtra = 0
        local hpMaxExtra = 0
        if targetEntityModel:hasRelatedNpc() then
            -- 关联Entity状态
            local relatedEntity = self.model.mBattleLoop:getEntityById(Unit.getRelatedNpcUnitId(targetEntity))
            if relatedEntity then
                hpExtra = Unit.hp(relatedEntity)
                hpMaxExtra = Unit.hpMax(relatedEntity)
            end
        end
        targetViewUI:updateData(id, hp, hpMax,
            mana, manaMax, rage, rageMax, newEnergy, newEnergyMax, hpExtra, hpMaxExtra)
        local shouldHideAllHpUIFlag = Unit.shouldHideAllHpUI(targetEntity)
        -- 刷新血条可见性
        targetViewUI:shouldHideAllHpUI(shouldHideAllHpUIFlag)
        local skill = Unit.skillInProgress(targetEntity)
        if skill then
            local targetIdOfTarget = Skill_targetId(skill)
            local targetofTargetEntity = self.model.mBattleLoop:getEntityById(targetIdOfTarget)
            local viewTot = self.views[targetIdOfTarget]
            if not cc.isDead(targetofTargetEntity) and viewTot then
                local entityModelTot = self:getEntityModelById(viewTot:getUnitModelId())
                targetViewUI:setDataRight(entityModelTot, viewTot, targetIdOfTarget, false)
                self.targetIdOfTarget = targetIdOfTarget
                id = Entity.getId(targetofTargetEntity)
                hp = Unit.hp(targetofTargetEntity)
                hpMax = Unit.hpMax(targetofTargetEntity)
                mana = Unit.mana(targetofTargetEntity)
                manaMax = Unit.manaMax(targetofTargetEntity)
                rage = Unit.rage(targetofTargetEntity)
                rageMax = Unit.rageMax(targetofTargetEntity)
                newEnergy = Unit.energy(targetofTargetEntity)
                newEnergyMax = Unit.energyMax(targetofTargetEntity)
                targetViewUI:updateDataRight(id,hp,hpMax,mana,manaMax,rage,rageMax,newEnergy,newEnergyMax)
            else
                targetViewUI:setDataRight(nil, nil, nil, false)
                self.targetIdOfTarget = 0
            end
        else
            targetViewUI:setDataRight(nil, nil, nil, false)
            self.targetIdOfTarget = 0
        end
    end

    --  刷新选中/未选中目标前后层变化
    local view = self.views[previousTargetId]
    if view then
        self:refreshViewLayer(view)
    end
    self:setAlreadAttack(false)
    view = self.views[self.targetId]
    if view then
        self:refreshViewLayer(view)
    end
--    print("======> BattleController:setTarget() finished =================")
end

function BattleController:clearTarget(isNeedNotifyServer)
--    print("======> BattleController:clearTarget()", self.targetId, isNeedNotifyServer)
    if self.targetId == 0 then
        self.targetIdOfTarget = 0
        return
    end
    self:setCameraOffset(0)
    local view = self.views[self.targetId]
    if self.mNewBattleUIView.topView then
        self.mNewBattleUIView.topView.targetView:clearData()
        self.mNewBattleUIView.topView.targetView:setData(nil, nil, nil, false)
        self.mNewBattleUIView.topView.targetView:setDataRight(nil, nil, nil, false)
    end
    self.targetId = 0
    self.targetIdOfTarget = 0
    if view then
        view:setCurrentPlayerTargetFlag(false)
        self:refreshViewLayer(view)
    end
    self:onForceLockTarget(false)
    if isNeedNotifyServer then
        --通知服务器清除目标
        self.model:setSkillTarget(0)
    end
end

function BattleController:getCurrentPlayerTargetId()
    for id,view in pairs(self.views) do
        if view:getIsCurrentPlayerTarget() then
            return id
        end
    end
    return nil
end

function BattleController:onSetKeepBasicAttack(event)
    self.model:setKeepBasicAttack(event.isKeep)
end

function BattleController:onUISetAutoBattle(event)
    local isAuto = event.isAuto
    local battleModel = self.model
    if battleModel:isRunning() then
        if BattleManager:isSingleMode() then
            battleModel.mBattleLoop:setAutoBattleInSingleMode(isAuto)
        else
            battleModel:C2S_SwitchAutoBattle(isAuto)
        end
    end
end

function BattleController:onSetAutoBattle(event)
    local isAuto = event.isAuto
    local battleModel = self.model
    if BattleManager:isSingleMode() then
        battleModel.mBattleLoop:setAutoBattleInSingleMode(isAuto)
    else
        battleModel:C2S_SwitchAutoBattle(isAuto)
    end
end

function BattleController:onForceLockTarget(isForceLocked)
    if self.isForceLocked ~= isForceLocked then
        self.model:forceLockTarget(isForceLocked)
    end
    self:setForceTargetLockedFlag(isForceLocked)
end

function BattleController:setBattleAuto(b)
    local isAuto = self.mAutoBattleView:isAutoBattle()
    if isAuto == b then
    else
        self.mAutoBattleView:setAutoBattle(b)
    end
end

function BattleController:setAutoBattleVisible(b)
    self.mAutoBattleView:setVisible(b)
end

function BattleController:setBattleUITouchEnabled(b)
    -- self.touchMaskLayer:setTouchEnabled(not b)
    self.touchMaskLayer:setSwallowTouches(not b)
end

function BattleController:setChatUiVisible(event)
    self:dispatchEvent("ChatUiVisible", {visible = event.visible})
end

function BattleController:setFloatTextVisible(event)
    local visible = event.visible
    self.actorFloatTextVisible = visible
    for k,v in pairs(self.views) do
        v:setFloatTextVisible(visible)
    end
end

function BattleController:getEntityViews()
	return self.views
end

function BattleController:getEntityView(uid)
	return self.views[uid]
end

function BattleController:getEntityModelById(uid)
	return self.model:getEntityModelById(uid)
end

function BattleController:getSummonEntityModelByNpcId(npcId)
	return self.model:getSummonEntityModelByNpcId(npcId)
end

function BattleController:getKofEntityModelByTeamIndex(teamId, index)
	return self.model:getKofEntityModelByTeamIndex(teamId, index)
end

function BattleController:newView(entityModel)
    local view
    if entityModel:isNpc() then
        view = self.entityFactory:newCreature(
            {
                id = entityModel:getNpcId(),
                dir = entityModel:getDir(),
            })
    elseif entityModel:isHero() then
        view = self.entityFactory:newHero(entityModel:getHeroAvatarParams())
    end
    -- TODO: view不需要存储model的数据
    view.unitModelId = entityModel:getUnitModelId()
    view.uid = entityModel:getUid()
    view.entityModel = entityModel
    view.specialHpMax = entityModel.specialHPMax
    view.isFakeNpc = entityModel.isFakeNpc
    view.canRevive = entityModel.canRevive
    view.mClassName = entityModel:getClassName()
    view.mLevel = entityModel:getLv()
    view.deathSound = entityModel.deathSound
    view.isSummonEntity = entityModel.isSummonEntity
    view.isRefreshEntity = entityModel.isRefreshEntity
    view.bIsNeutral = entityModel.bNeutral
    view.buildingType = entityModel.buildingType
    view.hideHead = entityModel:isHidingHead()
    view.isTimeMonster = entityModel.isTimeMonster
    return view
end

function BattleController:getCenterPoint(releaser,targets)
    local minX = nil
    local maxX = nil
    for i,target in ipairs(targets) do
        local p = target:getPositionX()
        if minX then
            minX = (releaser.dir == 1 and math.min(minX,p) or math.max(minX,p))
        else
            minX = p
        end
        if maxX then
            maxX = (releaser.dir == 1 and math.max(maxX,p) or math.min(maxX,p))
        else
            maxX = p
        end
    end
    return releaser.dir == 1 and minX+math.abs(maxX-minX)*0.5 or maxX+math.abs(maxX-minX)*0.5
end

function BattleController:hasKeepShake()
    local shakeNode = self.mapRoot
    if shakeNode then
        local action = shakeNode:getActionByTag(Enums.CommonActionTag.BattleScreenShake)
        if action then
            return true
        end
    end
    return false
end

function BattleController:stopKeepShake()
    local shakeNode = self.mapRoot
    if shakeNode then
        shakeNode:stopActionByTag(Enums.CommonActionTag.BattleScreenShake)
        shakeNode:setPosition(0,0)
    end
end

function BattleController:onSkilReleaseShake(shake)
    self:skillHitShake(shake)
end

function BattleController:skillHitShake(shake)
    local hitShake = nil
    if shake and shake > 0 then
        local shakeId = tonumber(shake)
        hitShake = ShakeConfig:getConfig(shakeId)
        -- dump(hitShake)
    end

    -- if hurtType == 0 and realAmount~=0 and hitShake then
    if hitShake then
        --如果没有 吟唱等持续震屏
        if not self:hasKeepShake() then
            self:screenShake(hitShake, Enums.CommonActionTag.BattleScreenHitShake)
        end
    end
end

function BattleController:screenShake(params, actionTag)
    local shakeNode = self.mapRoot
    if shakeNode then
        shakeNode:stopActionByTag(Enums.CommonActionTag.BattleScreenShake)
        shakeNode:stopActionByTag(Enums.CommonActionTag.BattleScreenHitShake)
        local actions = {}
        actions[#actions+1] = custom.Shaker:create(params.duration,params.strengthX,params.strengthY,params.interval, params.intervalFactor, params.dampingX, params.dampingXFactor, params.dampingY, params.dampingYFactor)
        actions[#actions+1] = cc.Place:create(cc.p(0,0))
        local action = cc.Sequence:create(actions)
        action:setTag(actionTag)
        shakeNode:runAction(action)
    end
end

function BattleController:startScreenSpalshShake(params)
    local params = ShakeConfig:getConfig(13)
    local shakeNode = self.mapRoot
    if shakeNode then
        local actions = {}
        actions[#actions+1] = custom.Shaker:create(params.duration,params.strengthX,params.strengthY,params.interval, params.intervalFactor, params.dampingX, params.dampingXFactor, params.dampingY, params.dampingYFactor)
        actions[#actions+1] = cc.Place:create(cc.p(0,0))
        local action = cc.Sequence:create(actions)
        action:setTag(Enums.CommonActionTag.BattleScreenSplashShake)
        shakeNode:runAction(action)
    end
end

function BattleController:stopScreenSpalshShake()
    local shakeNode = self.mapRoot
    if shakeNode then
        shakeNode:stopActionByTag(Enums.CommonActionTag.BattleScreenSplashShake)
        shakeNode:setPosition(0,0)
    end
end

function BattleController:getBattleTeamMembers()
    if not self.mTeamMembers then
        local teamp = {}
        for k,v in pairs(self.views) do
            if (not v:isEnemy()) and v:getUid() then
                table.insert(teamp, v)
            end
        end
        if #teamp > 0 then
            self.mTeamMembers = teamp
        end
    end

    return self.mTeamMembers
end

function BattleController:setEnginePauseState(b)
    -- 暂停战斗引擎
    b = b or false -- 默认 false
    if b then
        self:pauseBattle()
        self:pause()
    else
        self:resumeBattle()
        self:resume()
    end
    if self.model then
        self.model:setBattlePause(b)
    end
end

return BattleController
